haskell - Haskell 中的任意字符串生成器 (Test.QuickCheck.Gen)

标签 haskell testing quickcheck

我在 Real World Haskell Chapter 11 上挣扎quickCheck 代数数据类型的生成器实现。

在本书实现(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'] ++ " ~!@#$%^&*()")

我尝试了以下两个实现,但均未成功:

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 的实例:

  • 导入合格的 Test.QuickCheck.Arbitrary 但它没有实现 Arbitrary String 也没有
  • 正在安装 Test.RandomStrings hackage link

    instance 任意字符串 where 任意=做 n <- 选择 (8, 16)::Gen Int 返回 $ randomWord randomASCII n::Gen String

使用以下回溯:

$ 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

对于如何实现这个特定的生成器以及 - 更一般地说 - 在这些情况下如何进行,您有什么好的建议吗?

提前致谢

最佳答案

不要定义新的Arbitrary 类型类,而是导入Test.QuickCheck。它为您定义了其中的大部分实例。还要注意 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 ]

关于haskell - Haskell 中的任意字符串生成器 (Test.QuickCheck.Gen),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46728553/

相关文章:

ios - 从命令行自动执行 iOS monotuch GUI 测试

linux - 如何从 Linux 上的系统缓存中逐出文件?

与 Cabal 一起运行时,Haskell QuickCheck 测试无法正常运行

haskell - Haskell 中 (\x y z -> x y z) 的含义

parsing - haskell optparse-applicative : parsing a list of records that have multiple fields

angularjs - Protractor :don't wait for elements to appears in Dom

haskell - 如何快速检查 Enum 和 Bounded 类型的所有可能情况?

haskell - 如何为包装函数的类型编写任意实例?

haskell - 在多个包haskell中发现Control.Monad.Writer

haskell - 为什么 Haskell 的 `head` 在空列表上崩溃(或者为什么 *不* 它返回空列表)? (语言哲学)