2013-12-15 59 views
1

我有一個函數g1 = flip map . (flip take $ iterate (+1) 1) 我很奇怪,爲什麼我不能寫操作的優先級在Haskell

g1 = flip map . $ flip take $ iterate (+1) 1? 我知道$優先級最低,但不明白爲什麼我們可以點後有flip take $ iterate (+1) 1$但不是在g1

回答

3

注意,第二種形式導致解析錯誤,而不是一個類型的錯誤。你根本不能有兩個操作員並排。當你在.$,之間加上一個表達式時,運營商的優先級就會發揮作用。由於.具有更高的優先級,因此.$之間的表達式成爲.的右操作數,並且點運算符的結果成爲美元的左操作數。如果你想扭轉他們的優先級(或者假設他們已經寫了代碼),你會得到一個類型錯誤(除非類型恰好匹配)。

可以使用操作部分寫類似第二種形式:

g1 = (flip map .) $ flip take $ iterate (+1) 1 

但我要說最可讀的自由點符號是

g1 = flip map . flip take (iterate (+1) 1) 

而實際上iterate (+1) 1可縮短:

g1 = flip map . flip take [1..] 

接下來,有點desugaring幫助我們擺脫了flip take

g1 = flip map . enumFromTo 1 
0

讓我們一個更簡單的例子:

Prelude> :t id . (id) 
id . (id) :: c -> c 
Prelude> :t id . $ id 

<interactive>:1:6: parse error on input `$' 
Prelude> :t (id .) $ id 
(id .) $ id :: c -> c 

$運營商已經非常低優先級,因此它最後一次評估,並採取了功能作爲左邊參數:

Prelude> :i ($) 
($) :: (a -> b) -> a -> b  -- Defined in `GHC.Base' 
infixr 0 $ 

不幸的是,沒有括號,這些情況下你沒有得到適當的功能:

Prelude> :t id . 

<interactive>:1:5: 
    parse error (possibly incorrect indentation or mismatched brackets) 
Prelude> :t (id .) 
(id .) :: (a -> c) -> a -> c 
Prelude> :t flip take 
flip take :: [a] -> Int -> [a] 
Prelude> :t flip map . 

<interactive>:1:11: 
    parse error (possibly incorrect indentation or mismatched brackets) 
Prelude> 

這是一樣的道理,爲什麼你指的是加運算本身時需要寫(+)

Prelude> :t + 

<interactive>:1:1: parse error on input `+' 
Prelude> :t (+) 
(+) :: Num a => a -> a -> a 
Prelude> :t 1+ 

<interactive>:1:3: 
    parse error (possibly incorrect indentation or mismatched brackets) 
Prelude> :t (1+) 
(1+) :: Num a => a -> a 

結論:你根本不能有兩個運營商通過側直接側。