I am new to Haskell and want to generate an Arbitrary
tree.
So my first idea is to create an arbitary bool, if it is true then return an empty tree and else create a non-empty one:
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = do
createNonEmpty <- arbitrary
if createNonEmpty
then return Nil
else generateNonEmptyTree
But this pattern of creating the bool and use it just for that if seems a bit odd and it feels like there should be a more idiomatic way.
Is there already some kind of "monadic if" in the standard library that I could use like
arbitrary = ifM arbitrary (return Nil) (generateNonEmptyTree)
Or what else is the most idiomatic way to solve this?
For QuickCheck in particular, I'd use oneof
:
arbitrary = oneof [return Nil, generateNonEmptyTree]
It does essentially what you propose in your question (generate a one-off value, then use it immediately):
oneof :: [Gen a] -> Gen a
oneof [] = error "QuickCheck.oneof used with empty list"
oneof gs = choose (0,length gs - 1) >>= (gs !!)
But since it's a library function, this means you don't have to see the one-off values in your own code.
My general solution to the "use once binding" is -XLambdaCase
:
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = arbitrary >>= \case
True -> return Nil
False -> generateNonEmptyTree
Alternately, you could use something like
bool :: a -> a -> Bool -> a
bool f _ False = f
bool _ t True = t
(Bool
's equivalent to either
or foldr
)
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = bool generateNonEmptyTree (return Nil) =<< arbitrary
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With