最大链接.Haskell的运营商

Kit*_*sil 1 haskell

我正在尝试使用.运算符编写一个函数,它接受三个值并返回它们的最大值.

显然,以下工作

max3 a b c = max a (max b c)
max3 a b c = max a $ max b c
Run Code Online (Sandbox Code Playgroud)

但我想用..我试过了

max3 a b c = max a . max b c
Run Code Online (Sandbox Code Playgroud)

但得到错误

Couldn't match expected type `a0 -> Float' with actual type `Float'
In the first argument of `max', namely `b'
Run Code Online (Sandbox Code Playgroud)

我知道这个例子很愚蠢,但对正确的方法做了很好的解释,为什么会非常感激.

Dan*_*ner 6

回想一下定义(.):

(f . g) x = f (g x)
Run Code Online (Sandbox Code Playgroud)

你有表达

max a (max b c)
Run Code Online (Sandbox Code Playgroud)

它的右侧匹配(f . g) x,如果我们设置f = max a,g = max bx = c.在定义的左侧使用这些替换(.),我们得到:

(max a . max b) c = max a (max b c)
Run Code Online (Sandbox Code Playgroud)


Zet*_*eta 6

让我们在第一个例子中介绍一些括号:

max3 a b c = (max a) ((max b) c)
Run Code Online (Sandbox Code Playgroud)

现在将它与你上一个的那个进行比较:

max3 a b c = (max a) . ((max b) c)
Run Code Online (Sandbox Code Playgroud)

或者,如果我们用(.)前缀表示法写:

max3 a b c = (.) (max a) ((max b) c)
Run Code Online (Sandbox Code Playgroud)

现在我们明白为什么你会得到这个错误.为了进行类型检查,(max b) c需要是一个函数:

(.)       :: (b     -> c    )  -> (a -> b   ) -> a -> c
max a     ::  Float -> Float
max b c   ::                           Float
                                  ^^^^^^^^^^^
Run Code Online (Sandbox Code Playgroud)

如果我们使用约束版本,我们会收到更好的错误消息max:

maxFloat :: Float -> Float -> Float
maxFloat = max

max3 a b c = max a . max b c
Run Code Online (Sandbox Code Playgroud)

现在错误消息好多了:

Couldn't match expected type ‘a0 -> Float’ with actual type ‘Float’
Possible cause: ‘maxFloat’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘maxFloat b c’
In the expression: maxFloat a . maxFloat b c
Run Code Online (Sandbox Code Playgroud)

话虽这么说,让我们实际解决这个问题:

max3 a b c = max a ((max b) c)
           = (max a . max b) c
Run Code Online (Sandbox Code Playgroud)

请注意,您也可以写

max3 :: Ord a => a -> a -> a -> a   
max3 a b = max a . max b
Run Code Online (Sandbox Code Playgroud)