如果我β-约简下面的表达式:
foldr (mappend . Sum) 1 [2]
= (mappend . Sum) 2 (foldr (mappend . Sum) 1 [])
= (mappend . Sum) 2 1
= mappend (Sum 2) 1
...
望式:
// mappend (<>) :: Monoid a => a -> a -> a
我们可以看到最后一行有一个类型错误,因为常量1
应该属于Monoid
类(而它没有)。
然而,ghci
并没有抱怨。
为什么该表达式类型检查?
2条答案
按热度按时间7gs2gvoe1#
简短回答:
1
被解释为Sum a
,因此文件夹的类型为:其中
2
具有类型a
,并且1
具有类型Sum a
。**
Sum a
**是Num
的一个示例如果a
是Num
的一个示例,实际上,源代码是[src]:这意味着如果你写一个整数字面值,比如
1
,它可以被构造为Sum a
,对于任何a
,它是Num
的一个示例,所以1 :: Sum Integer
是Sum 1
。因此,这意味着
foldr
中的1
具有Sum a
类型,因此例如:bqucvtff2#
在Sum类型的文档中,您可以找到以下指示示例:
(当然,它应该在那里是完全合理的--不仅
Sum a
与a
"在道德上是相同的类型",而且Sum
显然被设计为几乎只与数字类型一起使用)。因为Haskell中的数值型文字(如
1
)可以是Num
类的任何类型的示例,所以mappend (Sum 2) 1
中没有类型错误,因为编译器会自动将其有效地转换为mappend (Sum 2) (Sum 1)
(因为在Sum a
的Num
示例中,fromInteger 1
将是Sum 1
)。