除了可读性和失去一般性之外,以下定义有什么问题:
maxPlusOne :: (Ord a, Num a) => a -> a -> a
maxPlusOne = (1+) . max
Run Code Online (Sandbox Code Playgroud)
编译器会抱怨它不能从中推断Num (a -> a)出来+.但在我看来它需要的是什么Num a => a -> a,这正是它的类型(1+).
这是错误:
<interactive>:5:52:
Could not deduce (Num (a -> a)) arising from a use of ‘+’
from the context (Ord a, Num a)
Run Code Online (Sandbox Code Playgroud)
让我们检查各个类型:
max :: (Ord a) => a -> a -> a
Run Code Online (Sandbox Code Playgroud)
好的,这需要一个a,并返回一个函数,它接受一个a并返回一个a.
(1 +) :: (Num a) => a -> a
Run Code Online (Sandbox Code Playgroud)
这很简单.需要一个数字a并添加一个.
如果我们记得那a . b相当于\q -> a (b q)我们从你的定义得到这个:
(1 +) . max == \q -> 1 + (max q)
Run Code Online (Sandbox Code Playgroud)
你能看到问题吗?你传递一个类型a -> a到(1 +),因为max是只得到一个说法.
这是如何解决它,同时保持无点风格.
maxPlusOne = (.) (1 +) . max
Run Code Online (Sandbox Code Playgroud)
这扩展到
maxPlusOne = \q -> (1 +) . max q
Run Code Online (Sandbox Code Playgroud)
扩展到
maxPlusOne = \q1 -> \q2 -> 1 + (max q1 q2)
Run Code Online (Sandbox Code Playgroud)
这是你想要的功能.
您还可以定义另一种类型的合成:
(.:) :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
(.:) f g a b = f (g a b)
Run Code Online (Sandbox Code Playgroud)
然后定义
maxPlusOne = (+ 1) .: max
Run Code Online (Sandbox Code Playgroud)