对于使用QuickCheck,我正在尝试实现任意实例:
import Test.QuickCheck
import Test.QuickCheck.Arbitrary (class Arbitrary, class Coarbitrary)
data Arith = Lit Int | Add Arith Arith | Neg Arith
derive instance arithEq :: Eq Arith
instance arbitraryFoo :: Arbitrary Arith where
arbitrary = arbLit <|> arbAdd <|> arbNeg where
arbAdd = do
a <- arbitrary
b <- arbitrary
pure $ Add a b
arbNeg = do
a <- arbitrary
pure $ Neg a
arbLit = do
x <- arbitrary
pure $ Lit x
但是PureScript告诉了我
The value of arbitraryFoo is undefined here, so this reference is not allowed.
当我根据错误消息更改代码以遵循指南时:
import Test.QuickCheck
import Test.QuickCheck.Arbitrary (class Arbitrary, class Coarbitrary)
import Control.Lazy
instance arbitraryFoo :: Arbitrary Arith where
arbitrary = fix $ \arb -> let
arbAdd = do
a <- arb
b <- arb
pure $ Add a b
arbNeg = do
a <- arb
pure $ Neg a
arbLit = do
x <- arbitrary
pure $ Lit x
in arbLit <|> arbAdd <|> arbNeg
我仍然有一些错误:
RangeError: Maximum call stack size exceeded
那么,我该如何解决?以及为什么Arbitrary
无法自动导出?
答案 0 :(得分:0)
为防止其生成无限递归结构,您应使生成器sized
,然后使resize
乘-1
,每次使其递归使用。
以下是使用该技术的JSON生成器的示例:https://github.com/purescript-contrib/purescript-argonaut-core/blob/37fc57c722851b1936c438db750aa8195dc630c7/src/Data/Argonaut/Gen.purs。尽管Gen
是用MonadGen
抽象的,但是如果您想实现Arbitrary
,则可以应用相同的原理。