Haskell foldr导致类型错误,而foldl没有';T
我正在学习“Haskell从第一原则开始编程”。在关于折叠列表的章节中,练习5f 当我评估Haskell foldr导致类型错误,而foldl没有';T,haskell,lazy-evaluation,fold,Haskell,Lazy Evaluation,Fold,我正在学习“Haskell从第一原则开始编程”。在关于折叠列表的章节中,练习5f 当我评估 foldr const 'a' [1..5] 我明白了 没有由文字“1”产生的(Num Char)实例 但是, foldl const 'a' [1..5] 我得到了'a' 我发现褶皱很懒,foldr不会穿过脊椎,foldl会穿过脊椎。但即使看看foldr和foldl的定义 foldr f z [] = z foldr f z (x:xs) = f x (foldr f z xs) fo
foldr const 'a' [1..5]
我明白了
没有由文字“1”产生的(Num Char)实例
但是,
foldl const 'a' [1..5]
我得到了'a'
我发现褶皱很懒,foldr
不会穿过脊椎,foldl
会穿过脊椎。但即使看看foldr和foldl的定义
foldr f z [] = z
foldr f z (x:xs) = f x (foldr f z xs)
foldl f z [] = z
foldl f z (x:xs) = foldl f (f z x) xs
我不明白为什么会有这种类型的错误。我猜想编译器正在根据z
(Char
)的类型推断x
(Num
)的类型,但我看不出它在哪里绘制连接,因为const
或f
不要求它的两个参数是同一类型
有什么想法吗?好的,看看
foldr::(a->b->b)->b->[a]->b的类型
从右边开始,显然必须有a
作为Num
和Enum
的实例(因为您使用[1..5]
)
接下来,您传入'a'
,这样您就有了b~Char
最后,您有函数的const
——const是const::a->b->a
——请注意,您现在必须有a~b
,因为您统一了
a -> b -> b
a -> b -> a
^^^^^
但这当然意味着'a'
必须是Num
实例的值,而Char
不是。。。这是您的错误(它抱怨1,因为从左开始,问题变得明显)
另一边的foldl
有foldl::(b->a->b)->b->[a]->b
所以现在你又有了a
一些Num
的实例,b
必须再次是Char
,但是现在const
正好合适(只需在const类型中切换b
和a
)好,看看foldr:(a->b->b->b->a]>b
从右边开始,显然必须有a
作为Num
和Enum
的实例(因为您使用[1..5]
)
接下来,您传入'a'
,这样您就有了b~Char
最后,您有函数的const
——const是const::a->b->a
——请注意,您现在必须有a~b
,因为您统一了
a -> b -> b
a -> b -> a
^^^^^
但这当然意味着'a'
必须是Num
实例的值,而Char
不是。。。这是您的错误(它抱怨1,因为从左开始,问题变得明显)
另一边的foldl
有foldl::(b->a->b)->b->[a]->b
因此,现在您又有了a
一些Num
的实例,b
必须再次是Char
,但现在const
正好适合(只需在const类型中切换b
和a
)foldl
和foldr
调用f
。这就是foldr
调用const x'a'
,但是foldl
调用const'a'x
。后者的结果是“a”,这很好,但后者的结果是x
,这是错误的,因为x
是一个Int
,并且结果应该与累加器具有相同的类型(Char
).foldl
和foldr
使用不同的参数顺序调用f
。这就是foldr
调用const x'a'
,但是foldl
调用const'a'x
。后者的结果是“a”,这很好,但后者的结果是x
,这是错误的,因为x
是一个Int
,并且结果应该与累加器的类型相同(Char
)。这是一个键入问题。foldl
的类型为
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
而foldr
类型为:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
当您将foldr
应用于const
时,您会得到:
foldr const :: Foldable t => b -> t b -> b
接下来,提供'a'
参数,得到
(foldr const 'a') :: Foldable t => t Char -> Char
因此,当您将[1..5]
作为参数传递时,它将尝试将t Char
与(Enum a,Num a)=>[a]
统一起来。TypeChar
是Enum
类的一个实例,但不是Num
,这就是您收到此错误消息的原因。这是一个键入问题。foldl
的类型为
foldl :: Foldable t => (b -> a -> b) -> b -> t a -> b
而foldr
类型为:
foldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
当您将foldr
应用于const
时,您会得到:
foldr const :: Foldable t => b -> t b -> b
接下来,提供'a'
参数,得到
(foldr const 'a') :: Foldable t => t Char -> Char
因此,当您将[1..5]
作为参数传递时,它将尝试将t Char
与(Enum a,Num a)=>[a]
统一起来。TypeChar
是Enum
类的一个实例,但不是Num
,这就是您收到此错误消息的原因。正如其他人所说,foldl
和foldr
中的参数顺序不同。改用翻转常数
:
> foldr (flip const) 'a' [1..5]
'a'
正如其他人所说,afoldl
和foldr
中的参数顺序是不同的。改用翻转常数
:
> foldr (flip const) 'a' [1..5]
'a'
啊,没错。当出现类型错误时,我必须养成先检查类型定义的习惯。谢谢是的-这就是你需要知道的99%的关于Haskell保暖的知识:检查类型;)啊,没错。当出现类型错误时,我必须养成先检查类型定义的习惯。谢谢是的-这就是你需要知道的99%的关于Haskell保暖的知识:检查类型;)“查看定义[…]我不明白为什么会出现这种类型错误”-诊断类型错误时不要查看定义,请查看类型!“看看这些定义[…]我搞不懂