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