否则的话是单子的
Monadic if else
我是 Haskell 的新手,想生成一棵 Arbitrary
树。
所以我的第一个想法是创建一个任意布尔值,如果它是真的那么 return 一棵空树,否则创建一个非空树:
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = do
createNonEmpty <- arbitrary
if createNonEmpty
then return Nil
else generateNonEmptyTree
但是这种创建 bool 并将其用于 if 的模式似乎有点奇怪,感觉应该有一种更惯用的方法。
标准库中是否已经有某种我可以使用的 "monadic if"
arbitrary = ifM arbitrary (return Nil) (generateNonEmptyTree)
或者还有什么最惯用的方法来解决这个问题?
我对 "use once binding" 的一般解决方案是 -XLambdaCase
:
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = arbitrary >>= \case
True -> return Nil
False -> generateNonEmptyTree
或者,您可以使用
bool :: a -> a -> Bool -> a
bool f _ False = f
bool _ t True = t
(Bool
等同于 either
或 foldr
)
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = bool generateNonEmptyTree (return Nil) =<< arbitrary
特别是对于 QuickCheck,我会使用 oneof
:
arbitrary = oneof [return Nil, generateNonEmptyTree]
它基本上完成了您在问题中提出的建议(生成一个 one-off 值,然后立即使用它):
oneof :: [Gen a] -> Gen a
oneof [] = error "QuickCheck.oneof used with empty list"
oneof gs = choose (0,length gs - 1) >>= (gs !!)
但由于它是一个库函数,这意味着您不必在自己的代码中查看 one-off 值。
我是 Haskell 的新手,想生成一棵 Arbitrary
树。
所以我的第一个想法是创建一个任意布尔值,如果它是真的那么 return 一棵空树,否则创建一个非空树:
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = do
createNonEmpty <- arbitrary
if createNonEmpty
then return Nil
else generateNonEmptyTree
但是这种创建 bool 并将其用于 if 的模式似乎有点奇怪,感觉应该有一种更惯用的方法。
标准库中是否已经有某种我可以使用的 "monadic if"
arbitrary = ifM arbitrary (return Nil) (generateNonEmptyTree)
或者还有什么最惯用的方法来解决这个问题?
我对 "use once binding" 的一般解决方案是 -XLambdaCase
:
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = arbitrary >>= \case
True -> return Nil
False -> generateNonEmptyTree
或者,您可以使用
bool :: a -> a -> Bool -> a
bool f _ False = f
bool _ t True = t
(Bool
等同于 either
或 foldr
)
instance (Arbitrary a) => Arbitrary (BinaryTree a)
arbitrary = bool generateNonEmptyTree (return Nil) =<< arbitrary
特别是对于 QuickCheck,我会使用 oneof
:
arbitrary = oneof [return Nil, generateNonEmptyTree]
它基本上完成了您在问题中提出的建议(生成一个 one-off 值,然后立即使用它):
oneof :: [Gen a] -> Gen a
oneof [] = error "QuickCheck.oneof used with empty list"
oneof gs = choose (0,length gs - 1) >>= (gs !!)
但由于它是一个库函数,这意味着您不必在自己的代码中查看 one-off 值。