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
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.