除了可读性和失去一般性之外,以下定义有什么问题:
MoveNext
编译器会抱怨它无法从maxPlusOne :: (Ord a, Num a) => a -> a -> a
maxPlusOne = (1+) . max
推断Num (a -> a)
。
但在我看来它需要的是+
,这正是Num a => a -> a
的类型。
这是错误:
(1+)
答案 0 :(得分:9)
让我们检查各个类型:
max :: (Ord a) => a -> a -> a
好的,这需要a
,并返回一个a
并返回a
的函数。
(1 +) :: (Num a) => a -> a
这很简单。它需要一个a
并添加一个。
如果我们回想起a . b
等同于\q -> a (b q)
,我们会从您的定义中得到:
(1 +) . max == \q -> 1 + (max q)
你能看到问题吗?您将类型a -> a
传递给(1 +)
,,因为max
只获得一个参数。
这是如何修复它,同时保持无点风格。
maxPlusOne = (.) (1 +) . max
这扩展到
maxPlusOne = \q -> (1 +) . max q
扩展为
maxPlusOne = \q1 -> \q2 -> 1 + (max q1 q2)
您希望的功能是什么。
您还可以定义另一种类型的构图:
(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.:) f g a b = f (g a b)
然后定义
maxPlusOne = (+ 1) .: max
答案 1 :(得分:-2)
我认为你过于数学地解释.
(如f
"" g
之后)。 .
只是:
(.) :: (b -> c) -> (a -> b) -> a -> c
所以它的语义意思是它需要一个参数a
,然后在g
上调用a
,然后在f
上调用g
。您可以将其定义为:
(.) f g x = f $ g x
虽然提出了Haskell扩展(如this one),但它使用类型系统来推导出多少"参数"要运输,有些人已经在模板Haskell中写了这个,它不是标准功能。
你怎么解决?
只需在函数头部查询至少一个参数x
:
maxPlusOne :: (Ord a, Num a) => a -> a -> a
maxPlusOne x = (1+) . max x
或完全指定:
maxPlusOne :: (Ord a, Num a) => a -> a -> a
maxPlusOne x y = (1+) $ max x y
或使用(.)
上的扩展程序。
maxPlusOne :: (Ord a, Num a) => a -> a -> a
maxPlusOne = (1+) $.$ max