关于何时撰写以及何时使用$的困惑

fly*_*zai 2 haskell

returnGreater :: (Ord a) => a -> a -> a
returnGreater a b
  | (a > b) = a
  | otherwise = b

returnGreatest2 :: (Ord a, Num a) => a -> a -> a -> (a, a)
returnGreatest2 a b c
  | (a > b) = (a, returnGreater b c)
  | otherwise = (b, returnGreater a c)

sumOfSquares :: (Num a) => (a, a) -> a
sumOfSquares (a, b) = a^2 + b^2
Run Code Online (Sandbox Code Playgroud)

鉴于上述功能,我很困惑为什么let x = sumOfSquares . returnGreatest2返回

<interactive>:13:24: error:
    • Couldn't match type ‘a -> a -> (a, a)’ with ‘(c, c)’
      Expected type: a -> (c, c)
        Actual type: a -> a -> a -> (a, a)
    • Probable cause: ‘returnGreatest2’ is applied to too few arguments
      In the second argument of ‘(.)’, namely ‘returnGreatest2’
      In the expression: sumOfSquares . returnGreatest2
      In an equation for ‘x’: x = sumOfSquares . returnGreatest2
    • Relevant bindings include
        x :: a -> c (bound at <interactive>:13:5)
Run Code Online (Sandbox Code Playgroud)

sumOfSquares $ returnGreatest2 3 5 7做对了.由于出来returnGreatest2的类型与sumOfSquares预期的类型相同,我认为我能够组成它们.

che*_*ner 5

组成和卷曲可能有点混乱.sumOfSquares . returnGreatest2是相同的\x -> sumOfSquares (returnGreatest2 x),但是类型returnGreatest2 x(Ord a, Num a) => a -> a -> (a, a).在最终获得可接受的类型值之前,您需要传递所有预期的参数.(Ord a, Num a) => (a, a)sumOfSquares

另一方面,sumOfSquares $ returnGreatest2 3 5 7解析相同sumOfSquares $ (returnGreatest2 3 5 7); 的($)操作者具有比功能应用低优先级(或任何其它操作者,对于这个问题).

要真正构成这两个函数,需要多个组合层:

let f = ((sumOfSquares .) . ) . returnGreatest2
Run Code Online (Sandbox Code Playgroud)