我有一个函数,定义如下,该函数被赋予布尔列表的列表并返回一个布尔:
evaluates :: [[Bool]] -> Bool
我尝试了以下方法:
evaluates :: [[Bool]] -> Bool
evaluates ((y:ys):xs) = (y && (head ys)) || evaluates (tail xs)
但这不起作用。
我期望的结果是:
[True && False && True] || [True] || [False && False]] = True
对于以下项的输入:[[True, False, True], [True], [False, False]]
答案 0 :(得分:11)
您尝试在单个函数中执行太多操作。让我们分三步解决问题:
Bool
列表的函数,并返回这些Bool
的逻辑与; Bool
的列表并返回这些Bool
的逻辑或;和[Bool]
列表的函数,首先将其与第一个函数映射,然后在其上执行第二个函数。我们可以使用foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
实现第一个功能:
_and :: [Bool] -> Bool
_and = foldr (&&) True
事实上,Haskell的前奏已经具有一个and :: Foldable f => f Bool -> Bool
功能。
第二个功能也可以用foldr
来实现:
_or :: [Bool] -> Bool
_or = foldr (||) False
Haskell的前奏已经具有一个or :: Foldable f => f Bool -> Bool
功能。
现在我们可以用map :: (a -> b) -> [a] -> [b]
来定义evaluate
:
evaluate :: [[Bool]] -> Bool
evaluate = _or . map _and
我们甚至可以将以上内容概括为两个(可能是不同的)Foldable
:
evaluate :: (Foldable f, Foldable g) => f (g Bool) -> Bool
evaluate = foldr ((||) . and) False
或者像@DanielWagner所说,我们可以使用any :: Foldable f => (a -> Bool) -> f a -> Bool
:
evaluate :: (Foldable f, Foldable g) => f (g Bool) -> Bool
evaluate = any and
例如:
Prelude> evaluate [[True, False, True], [True], [False, False]]
True
Prelude> evaluate [Just False, Just False, Nothing]
True
Prelude> evaluate [Just False, Just False, Just False]
False
Prelude> evaluate (Just [True, False, True])
False
Prelude> evaluate (Just [True, True, True])
True