Function application in Haskell and the difference between (), . and $
there are different function of Application方式在Haskell,but that each has its specificities似乎。我想了解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | Prelude> 100 / fromIntegral( length [1..10] ) 10.0 Prelude> 100 / fromIntegral . length [1..10] <interactive>:193:22: error: * Couldn't match expected type `a -> Integer' with actual type `Int' * Possible cause: `length' is applied to too many arguments In the second argument of `(.)', namely `length [1 .. 10]' In the second argument of `(/)', namely `fromIntegral . length [1 .. 10]' In the expression: 100 / fromIntegral . length [1 .. 10] * Relevant bindings include it :: a -> c (bound at <interactive>:193:1) Prelude> 100 / fromIntegral $ length [1..10] <interactive>:194:1: error: * Non type-variable argument in the constraint: Fractional (Int -> b) (Use FlexibleContexts to permit this) * When checking the inferred type it :: forall b. (Num b, Fractional (Int -> b)) => b Prelude> |
为什么不同的行为在this is the only parentheses和房屋,
其中只有一种实际上是内置的函数应用程序语法:您称之为
1 2 3 4 5 6 | 〖??〗: 100 / fromIntegral( length [1..10] ) ≡ (/) 100 (fromIntegral (length [1..10])) 〖??〗: 100 / fromIntegral . length [1..10] ≡ (/) 100 ((.) fromIntegral (length [1..10])) 〖??〗: 100 / fromIntegral $ length [1..10] ≡ ($) ((/) 100 fromIntegral) (length [1..10]) |
它们之所以如此不同,是因为中缀优先规则:每个中缀运算符都有一个固定性声明。与此相关的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | Prelude> :i . (.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in ‘GHC.Base’ infixr 9 . Prelude> :i $ ($) :: forall (r :: GHC.Types.RuntimeRep) a (b :: TYPE r). (a -> b) -> a -> b -- Defined in ‘GHC.Base’ infixr 0 $ Prelude> :i / class Num a => Fractional a where (/) :: a -> a -> a ... -- Defined in ‘GHC.Real’ infixl 7 / |
这告诉我们:
1 | ($) ((/) ((.) w x) y) z |
(函数应用程序本身——您称之为
好的,上面的饮食表达式看起来很混乱,所以我们再来看看加糖的形式,但是仍然使用明确的括号分组:
1 2 3 | 〖??〗 ≡ 100 / (fromIntegral (length [1..10])) 〖??〗 ≡ 100 / (fromIntegral . (length [1..10])) 〖??〗 ≡ (100 / fromIntegral) $ (length [1..10]) |
应该立即清楚的是??]不可能是对的,不管操作符实际做了什么:你试图用一个函数来除一个数字,这是没有意义的!
什么??]在解析方面看起来很明智,但在类型方面却没有意义:
实际上,可以使用composition运算符编写此表达式,但在将函数中的任何一个应用于参数(并且只将参数应用于composition链)之前,必须先组合这些函数:
1 2 3 4 | 〖??′〗: 100 / (fromIntegral . length) [1..10] ≡ 100 / (\x -> fromIntegral (length x)) [1..10] ≡ 100 / fromIntegral (length [1..10]) ≡ 〖??〗 |
至于
1 2 3 4 | 〖??′〗: 100 / (fromIntegral $ length [1..10]) ≡ 100 / ((fromIntegral) (length [1..10])) ≡ 100 / fromIntegral (length [1..10]) ≡ 〖??〗 |
1 |
减少到:
1 | fromIntegral . 10 |
但是