自定义类列表类型的 Arbitrary 实例

zer*_*ing 1 haskell

我有以下数据类型(如列表):

  data List a =
      Nil
    | Cons a (List a)
    deriving (Eq, Show)
Run Code Online (Sandbox Code Playgroud)

并创建了一个实例Monoid

  instance Monoid (List a) where
    mempty = Nil
    mappend Nil ys = ys
    mappend (Cons x xs) ys = Cons x (mappend xs ys) 
Run Code Online (Sandbox Code Playgroud)

我尝试编写一个实例来Arbitrary测试后者,但无法完成它:

  instance Arbitrary a => Arbitrary (List a) where
    arbitrary = do  
Run Code Online (Sandbox Code Playgroud)

请帮助我完成该功能。

Igo*_*dov 5

使用怎么样使用oneof

instance Arbitrary a => Arbitrary (List a) where
  arbitrary = oneof [pure Nil, Cons <$> arbitrary <*> arbitrary]
Run Code Online (Sandbox Code Playgroud)

它将生成空值Nil或非空列表。oneof获取值列表Gen a,这就是为什么pure并且<$>需要<*>将值包装到Gen. return并且liftM2也可以使用。

在定义了instance一个简单的测试后:

prop_nil_mappend :: List Int -> Bool
prop_nil_mappend xs = mappend Nil xs == xs

main :: IO ()
main = quickCheck prop_nil_mappend
Run Code Online (Sandbox Code Playgroud)

顺便说一句,在大多数情况下Nil,它不如非空列表有用,因此您可以定义其中每个列表的生成频率:

instance Arbitrary a => Arbitrary (List a) where
  arbitrary =
    frequency [(1, pure Nil),
               (5, Cons <$> arbitrary <*> arbitrary)]
Run Code Online (Sandbox Code Playgroud)