Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ssh/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 为什么foldl1无法应用(=)运算符?_Haskell_Functional Programming_Higher Order Functions_Fold - Fatal编程技术网

Haskell 为什么foldl1无法应用(=)运算符?

Haskell 为什么foldl1无法应用(=)运算符?,haskell,functional-programming,higher-order-functions,fold,Haskell,Functional Programming,Higher Order Functions,Fold,从《序曲》: foldl1:它接受 列表并将该函数应用于 然后用 这个结果和第三个参数以及 等等 为什么不可能写这样的东西 foldl1 (==) [6, 6, 6] foldl1 (\x y -> x == y) [6, 6, 6] 编辑:安塔尔指出我的推理是错误的。下面是评论的相关部分,给出了真正的理由(我觉得逐字逐句的回答很糟糕,但是这个答案被接受了,所以我不能删除它): 这不起作用的原因是foldl1的类型是(a->a->a)->[a]->a,但是(==)的类型是Num a=>a

从《序曲》:

foldl1:它接受 列表并将该函数应用于 然后用 这个结果和第三个参数以及 等等

为什么不可能写这样的东西

foldl1 (==) [6, 6, 6]
foldl1 (\x y -> x == y) [6, 6, 6]

编辑:安塔尔指出我的推理是错误的。下面是评论的相关部分,给出了真正的理由(我觉得逐字逐句的回答很糟糕,但是这个答案被接受了,所以我不能删除它):

这不起作用的原因是
foldl1
的类型是
(a->a->a)->[a]->a
,但是
(==)
的类型是
Num a=>a->Bool
。由于
Bool
不是
Num
(==)
类型与
a->a->a
不匹配,因此
foldl1
的应用被拒绝。如果它被接受了,那么您最终会遇到这样一种情况:您试图执行
True==6
,但是类型系统从一开始就不会让您走那么远

原始答案(后一种推理不正确):


=
将使用两个
Int
s并返回一个
Bool
。第一次迭代后,示例列表变为
[True,6]
。然后它尝试将
True
与失败的
6
进行比较。

EDIT:Antal指出我的推理是错误的。下面是评论的相关部分,给出了真正的理由(我觉得逐字逐句的回答很糟糕,但是这个答案被接受了,所以我不能删除它):

这不起作用的原因是
foldl1
的类型是
(a->a->a)->[a]->a
,但是
(==)
的类型是
Num a=>a->Bool
。由于
Bool
不是
Num
(==)
类型与
a->a->a
不匹配,因此
foldl1
的应用被拒绝。如果它被接受了,那么您最终会遇到这样一种情况:您试图执行
True==6
,但是类型系统从一开始就不会让您走那么远

原始答案(后一种推理不正确):


=
将使用两个
Int
s并返回一个
Bool
。第一次迭代后,示例列表变为
[True,6]
。然后,它尝试将
True
与失败的
6
进行比较。

如果要检查列表中的所有元素是否相等,可以使用快速解决方案

allEqual [] = True --(edit: this case is not necessary as pointed out by sepp2k)
allEqual xs = all (== head xs) xs
有人会写一个更优雅的方式来做这件事,我相信,但这是有用的


编辑:感谢sepp2k的建议。

如果您想检查列表中的所有元素是否相等,可以使用快速解决方案

allEqual [] = True --(edit: this case is not necessary as pointed out by sepp2k)
allEqual xs = all (== head xs) xs
有人会写一个更优雅的方式来做这件事,我相信,但这是有用的


编辑:感谢sepp2k的建议。

如果您想使用折叠,我建议进行以下修改:

allEqual xs = foldr (\x acc -> x == head xs && acc) True xs
这与已经建议的
all
方法非常相似。请注意,此方法和
all
方法都可以在无限列表上工作(只要答案是
False

对于非常长的有限列表,在非常罕见的情况下,通过严格的左折叠可以获得更好的性能:

allEqual xs = foldl' (\acc x -> acc && x == head xs) True xs

但是对于这个问题,右折叠通常更好,因为(在这个实现中)它只执行相当于
length$takeWhile(=head xs)xs
的许多折叠步骤。左侧折叠每次将执行
length xs
折叠步骤。

如果您想使用折叠,我建议进行以下修改:

allEqual xs = foldr (\x acc -> x == head xs && acc) True xs
这与已经建议的
all
方法非常相似。请注意,此方法和
all
方法都可以在无限列表上工作(只要答案是
False

对于非常长的有限列表,在非常罕见的情况下,通过严格的左折叠可以获得更好的性能:

allEqual xs = foldl' (\acc x -> acc && x == head xs) True xs

但是对于这个问题,右折叠通常更好,因为(在这个实现中)它只执行相当于
length$takeWhile(=head xs)xs
的许多折叠步骤。左侧折叠每次将执行
length xs
折叠步骤。

这里是另一个版本:

allEqual xs = and $ zipWith (==) xs (tail xs)

以下是另一个版本:

allEqual xs = and $ zipWith (==) xs (tail xs)

仅凭直觉,但对前两个应用相等运算符会生成布尔值。我怀疑将布尔值与整数进行比较是否有意义。这只是一种预感,但对前两个应用相等运算符会产生布尔值。我怀疑将布尔值与整数进行比较是否有意义。您的第一句话是正确的,但在Haskell中,True不能转换为1@马可:谢谢,这很有道理。真可惜我没想到这件事!:)@维泰克博士,谢谢。我的haskell实用性不强。marcog:不用担心——如果OP曾经用另一种语言重新创建过这个功能,并且想知道为什么,例如,这段代码会在[6,6,1]上给出不正确的结果,那么这是一个很好的提示。我不想追踪那个虫子…这还是不对的。列表
[True,6]
不能存在于Haskell中,因为它的类型不正确;即使可以,这也会使事情在运行时失败,而不是在编译时失败。这不起作用的原因是
foldl1
的类型是
(a->a->a)->[a]->a
,但是
(==)
的类型是
Num a=>a->Bool
。由于
Bool
不是
Num
(==)
类型与
a->a->a
不匹配,因此
foldl1
的应用被拒绝。如果它被接受,你最终会遇到这样一种情况:你试图做
True==6
,但是类型系统从一开始就不会让你走那么远。你的第一句话是正确的,但在Haskell中True不能转换为1@马可:谢谢,这很有道理。真可惜我没想到这件事!:)@维泰克博士,谢谢。我的haskell实用性不强。marcog:不用担心,如果OP在另一个应用程序中重新创建此功能,这是一个很好的说明