Haskell 如何使用映射/过滤器实现此功能
我应该提出一个函数Haskell 如何使用映射/过滤器实现此功能,haskell,higher-order-functions,Haskell,Higher Order Functions,我应该提出一个函数和::[Bool]->Bool,其中(和xs)只有在xs不包含假元素时才为真 我完全能够用递归来写这个。我甚至尝试使用map,但map总是返回一个列表,这与我的返回类型冲突 下面是我使用递归的代码:(它工作得很好) 我试着用map做这件事:(这永远不会起作用) 那么,我该如何使用map、filter或foldr来实现这个疯狂的功能呢?谢谢筛选真值并检查结果是否为空列表: and' :: [Bool] -> Bool and' = null . filter (== Fal
和::[Bool]->Bool
,其中(和xs)
只有在xs不包含假元素时才为真
我完全能够用递归来写这个。我甚至尝试使用map,但map总是返回一个列表,这与我的返回类型冲突
下面是我使用递归的代码:(它工作得很好)
我试着用map做这件事:(这永远不会起作用)
那么,我该如何使用map、filter或foldr来实现这个疯狂的功能呢?谢谢筛选
真值
并检查结果是否为空列表:
and' :: [Bool] -> Bool
and' = null . filter (== False)
使用foldr
的更经典方法:
and'' :: [Bool] -> Bool
and'' = foldr (&&) True
foldr
是一条路:
有多种方法可以达到这个目的。首先,将折叠视为在成对元素之间插入二进制操作:
foldr c n [x1,x2,x3,...,xn] =
x1 `c` (x2 `c` (x3 `c` (... `c` (xn `c` n))))
所以在这种情况下,
foldr (&&) True [x1,x2,x3,...,xn] =
x1 && x2 && x3 && ... && xn && True
请注意,&&
是右关联的,因此不需要括号
另一种方法是找出如何将给定的递归形式转换为折叠。阅读格雷厄姆·赫顿(Graham Hutton)的《褶皱的普遍性和表现力教程》(The Tutorial on The University and Expressiveness of Fold)可以了解这一点
从递归形式开始:
and::[Bool]->Bool
and [] =True
and (x:xs)
| (x == True) = and (xs)
| otherwise = False
现在没有理由问x==True
,因为这实际上与直接测试x
是一样的。函数参数周围不需要额外的括号。我们可以这样重写:
and [] = True
and (x:xs)
| x = and xs
| otherwise = False
现在,让我们看看是否可以将其写成折叠:
and xs = foldr c n xs
因为和[]=True
我们知道n=True
:
and xs = foldr c True xs
现在来看递归情况:
and (x:xs)
| x = and xs
| otherwise = False
您可以看到,这只取决于x
和和xs
。这意味着我们将能够提出一个c
,这样折叠将正确:
c x r
| x = r
| otherwise = False
r
是将和
应用于列表其余部分的结果。但是这个c
函数是什么?只是(&&&)
所以我们得到了
and xs = foldr (&&) True xs
在每个步骤中,foldr
传递当前元素和折叠列表其余部分的结果
我们实际上不需要那个xs
参数,所以我们可以编写
and = foldr (&&) True
以与过滤器类似的方式考虑
takeWhile
,但在遇到第一个False
时停止过滤,如下所示
and' :: [Bool] -> Bool
and' xs = xs == takeWhile (== True) xs
第二种方法不适用于空列表。“第一个不够懒。”德弗尔,更正。我并不是说第一个解决方案是完美的。问题是:“那个么我到底该如何使用map、filter或foldr来实现这个疯狂的功能呢?”。所以我展示了如何用不同的方法来做它。@dfeuer作为一个非专家,我很好奇你说它不够懒是什么意思。它适用于无限列表。@Mattams,我们希望
和(False:undefined)
是False
,但是使用上面基于过滤器的定义,它是undefined
。啊,我明白了,谢谢。更懒惰的解决方案是和'=null。过滤器(=False)
。谢谢。
and = foldr (&&) True
and' :: [Bool] -> Bool
and' xs = xs == takeWhile (== True) xs