第一次發帖是完全正確的,但是因爲你縫有更多的問題,這是我嘗試...
當你試着去了解這段代碼做什麼,瞭解什麼樣的功能做的很重要以及以何種順序它們被應用,所以讓我們來看看:
lines :: String -> [String] --takes a String and returns a list of Strings
tail :: [a] -> [a] --takes a (nonempty) list and drops the head (a list containing the rest)
(.) :: (b -> c) -> (a -> b) -> a -> c --function composition
現在這是很重要...函數組合是右關聯的,具有9的優先級(最高級!)
map :: (a -> b) -> [a] -> [b] --applies (a -> b) to every element of [a]
現在你的代碼:
let f = map tail.tail.lines
相當於
let f x = map tail ((tail.lines) $ x)
這意味着你將映射tail
超過lines
結果的tail
的結果。這種行爲是因爲(.)
以及函數應用程序在Haskell中是正確關聯的。值得注意的是,(tail.lines)
是部分函數應用的結果(如您從(。)的類型簽名可以看出a
缺失...因此它將返回一個函數,該函數需要一個a
並返回一個c
)
在你以後的例子:
let f = map (tail.tail).lines
應用程序的順序由parenthesizes改變......這個版本相當於:
let f x = map (tail.tail) (lines $ x)
所以將間對lines
的結果執行ap tail.tail
(將頭部放下兩次)。
關鍵是理解關聯性。它確定哪個函數首先在沒有加括號的情況下被應用,以及函數是否具有相同的優先級。
我希望這可以幫助您瞭解差異。
我不得不克服學習Haskell的第一個障礙之一是將空間視爲非常緊密的綁定。在空間是詞分隔符的自然語言環境中,它似乎在做'map(tail.tail.lines)'(因爲函數組合之間沒有空間,它必須更緊密地綁定,對嗎?)但當然這在Haskell中並不是這樣。 –
對不起,我仍然不明白爲什麼兩個輸出不同,我想知道haskell解析代碼的方式。 –
感謝您的幫助。中國有句老話:醍醐灌頂 –