为什么没有组成两个功能?

时间:2015-09-18 15:57:10

标签: haskell types

除了可读性和失去一般性之外,以下定义有什么问题:

MoveNext

编译器会抱怨它无法从maxPlusOne :: (Ord a, Num a) => a -> a -> a maxPlusOne = (1+) . max 推断Num (a -> a)。 但在我看来它需要的是+,这正是Num a => a -> a的类型。

这是错误:

(1+)

2 个答案:

答案 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

或使用(.)上的扩展程序。

如果您使用jaspervdj's extension

maxPlusOne :: (Ord a, Num a) => a -> a -> a
maxPlusOne = (1+) $.$ max