2017-10-13 120 views
1

我正在努力Real World Haskell Chapter 11quickCheck代数数据类型的生成器实现。Haskell中的任意字符串生成器(Test.QuickCheck.Gen)

继书执行(这是2008年出版),我想出了以下内容:

-- file: ch11/Prettify2.hs 
module Prettify2(
    Doc(..) 
) where 

data Doc = Empty 
     | Char Char 
     | Text String 
     | Line 
     | Concat Doc Doc 
     | Union Doc Doc 
     deriving (Show, Eq) 

我的任意实施:

-- file: ch11/Arbitrary.hs 

import System.Random 
import Test.QuickCheck.Gen 
import qualified Test.QuickCheck.Arbitrary 


class Arbitrary a where 
    arbitrary :: Gen a 
    -- elements' :: [a] => Gen a {- Expected a constraint, but ‘[a]’ has kind ‘*’ -} 
    -- choose' :: Random a => (a, a) -> Gen a 
    -- oneof' :: [Gen a] -> a 

data Ternary = Yes 
      | No 
      | Unknown 
      deriving(Eq, Show) 

instance Arbitrary Ternary where 
    arbitrary = do 
     n <- choose (0, 2) :: Gen Int 
     return $ case n of 
         0 -> Yes 
         1 -> No 
         _ -> Unknown 

instance (Arbitrary a, Arbitrary b) => Arbitrary (a, b) where 
    arbitrary = do 
     x <- arbitrary 
     y <- arbitrary 
     return (x, y) 

instance Arbitrary Char where 
    arbitrary = elements (['A'..'Z'] ++ ['a' .. 'z'] ++ " [email protected]#$%^&*()") 

我尝试以下两种实现无成功:

import Prettify2 
import Control.Monad(liftM, liftM2) 

instance Arbitrary Doc where 
    arbitrary = do 
     n <- choose (1,6) :: Gen Int 
     case n of 
      1 -> return Empty 
      2 -> do x <- arbitrary 
        return (Char x) 
      3 -> do x <- arbitrary 
        return (Text x) 
      4 -> return Line 
      5 -> do x <- arbitrary 
        y <- arbitrary 
        return (Concat x y) 
      6 -> do x <- arbitrary 
        y <- arbitrary 
        return (Union x y) 

instance Arbitrary Doc where 
    arbitrary = 
     oneof [ return Empty 
       , liftM Char arbitrary 
       , liftM Text arbitrary 
       , return Line 
       , liftM2 Concat arbitrary arbitrary 
       , liftM2 Union arbitrary arbitrary ] 

但它不编译自No instance for (Arbitrary String)

我试图然后执行实例通过以下方式Arbitrary String

  • import qualified Test.QuickCheck.Arbitrary,但它没有实现Arbitrary String既不
  • 安装Test.RandomStringshackage link

    例如任意字符串,其中 任意= do n < - 选择(8,16):: Gen Int 返回$ randomWord randomASCIIň::创字符串

用下面的回溯:

$ ghci 
GHCi, version 7.10.3: http://www.haskell.org/ghc/ :? for help 
Prelude> :l Arbitrary.hs 
[1 of 2] Compiling Prettify2  (Prettify2.hs, interpreted) 
[2 of 2] Compiling Main    (Arbitrary.hs, interpreted) 

Arbitrary.hs:76:9: 
    The last statement in a 'do' block must be an expression 
     return <- randomWord randomASCII n :: Gen String 
Failed, modules loaded: Prettify2 

你有关于如何实现这一特定发电机任何好的建议和 - 更一般地 - 如何在这些情况下进行?

预先感谢您

回答

2

不要定义一个新的Arbitrary类型的类,进口替代Test.QuickCheck。它为你定义了大部分这些实例。另外要小心快速检查的版本,RWH假设第1版

产生的全面实施将是:

-- file: ch11/Arbitrary.hs 

import Test.QuickCheck 
import Prettify2 
import Control.Monad(liftM, liftM2) 

data Ternary = Yes 
      | No 
      | Unknown 
      deriving(Eq, Show) 

instance Arbitrary Ternary where 
    arbitrary = do 
     n <- choose (0, 2) :: Gen Int 
     return $ case n of 
         0 -> Yes 
         1 -> No 
         _ -> Unknown 


instance Arbitrary Doc where 
    arbitrary = 
     oneof [ return Empty 
       , liftM Char arbitrary 
       , liftM Text arbitrary 
       , return Line 
       , liftM2 Concat arbitrary arbitrary 
       , liftM2 Union arbitrary arbitrary ] 
+0

RWO?它通常缩写为RWH。 – Zeta

+0

啊oops,我和OCaml混淆了。 –