如何让Quickcheck检查下面代码中的传递属性?代码表示一堆物理块。块只能使用操作MoveOnto bl b2 s
放置在空表或另一个块上,操作b2
被移动到堆栈或表bl
上的s
中。我的Quickcheck尝试只是挂起并且没有产生任何结果。
import Test.QuickCheck
data Block = Block Int deriving (Show,Eq)
data Stack = EmptyTable | MoveOnto Block Block Stack deriving (Show,Eq)
isOn :: Block -> Block -> Stack -> Bool
isOn b1 b2 (MoveOnto b3 b4 s) | ((b1 == b3) && (b4 == b2)) || (isOn b4 b2 s) = True
isOn _ _ _ = False
b1' = Block 1
b2' = Block 2
b3' = Block 3
b4' = Block 4
b5' = Block 5
b6' = Block 6
b7' = Block 7
b8' = Block 8
-- Hand made test
testTransitivityTrue b1 b2 b3 b4 b5 = isOn b1 b5 (MoveOnto b1 b2 (MoveOnto b2 b3 (MoveOnto b3 b4 (MoveOnto b4 b5 EmptyTable))))
instance Arbitrary (Block) where
arbitrary = arbitrary
instance Arbitrary (Stack) where
arbitrary = oneof [return EmptyTable, MoveOnto <$> arbitrary <*> arbitrary <*> arbitrary]
prop_pass b1 b2 s = isOn b1 b2 (MoveOnto b1 b2 s)
答案 0 :(得分:4)
它挂起,因为在尝试构造任意Block
时,您执行无限递归。事实上:
instance Arbitrary (Block) where
arbitrary = arbitrary
所以这就意味着你写了一个可以通过生成任意块来生成任意块。这当然行不通。您可以定义任意Int
,然后使用以下内容构造一个块:
instance Arbitrary (Block) where
arbitrary = fmap Block arbitrary
现在可以构造任意块,也可以构造任意堆栈,尽管如果我们将概率建模为统一的话,严格意义上也可能会运行无限时间(由于技术原因) ,我们知道堆栈建设最终会停止。