How can I get Quickcheck to check the transitive property in the code below? The code represents a stack of physical blocks. Blocks can only be placed on an empty table or another block using the operation MoveOnto bl b2 s
, which is read as b2
is moved into and onto bl
on stack or table s
. My Quickcheck attempt just hangs and produces no result.
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)
It hangs since in the attempt to construct an arbitrary Block
, you perform endless recursion. Indeed:
instance Arbitrary (Block) where
So here that means that you wrote that one can generate an arbitrary block by generating an arbitrary block. This will of course not work. You can define an arbitrary Int
, and then construct a block for that with:
instance Arbitrary (Block) where
arbitrary = arbitrary
Now that arbitrary blocks can be constructed, arbitrary stacks can be constructed as well, although there is strictly speeking a possibility that this will run for an infinite time as well (due to technical reasons), if we model the probabilities as uniform, we know that eventually the stack building will stop.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.