为什么不组成两个功能?

Bla*_*adt 2 haskell types

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

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)

AJF*_*mar 9

让我们检查各个类型:

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)