2016-09-09 112 views
0

我剛開始在uni學習Haskell,在玩弄它的時候,我偶然發現了一個我似乎無法理解的問題。 下面的代碼給了我希望的結果:Haskell函數組合方法

import Data.List 
list = ["Hello", "world"] 

main = print $ intercalate " something " (reverse (map reverse list)) 

輸出:

"dlrow something olleH" 

但我想寫用點​​來代替括號中的「主」的功能,因此它試圖:

main = print $ intercalate " something " . reverse . map reverse list 

但是,這給我以下錯誤:

test.hs:5:54: error: 
    • Couldn't match expected type ‘a0 -> [[Char]]’ 
        with actual type ‘[[Char]]’ 
    • Possible cause: ‘map’ is applied to too many arguments 

我認爲這些圓點與括號完全相同:函數組合。爲什麼括號會起作用,而這些點會給我一個類型相關的錯誤?任何幫助將不勝感激!

回答

3

括號不意味着功能組成。他們只是指「將這個子表達式分組」。當然,你可以使用他們作出功能組合物的鏈:爲以下定義c中的功能fgh

c x = f (g (h x)) 

此的組合物還可以寫爲:

c = f . g . h 

因此,你可以

main = print $ c list 
where c = intercalate " something " . reverse . map reverse 

但是,如果您再次內聯c,則需要注意不要搞亂解析規則:只在該構圖鏈的右側編寫list不會這樣,因爲函數應用程序比任何中綴運算符(包括. ,儘管這實際上是最緊密的中綴操作符)。即,

intercalate " something " . reverse . map reverse list 

實際上解析爲

(intercalate " something ") . (reverse) . (map reverse list) 

但是,這不是你想要的。您需要確保list實際上是整個合成鏈的參數,而不僅僅是它的最後一個元素;做到這一點的最佳方式是與$操作:

intercalate " something " . reverse . map reverse $ list 

$最低 prevedence,因此這被分析爲

((intercalate " something ") . (reverse) . (map reverse)) (list) 

或者,您也可以申請map reverselist馬上 - 這本身並沒有錯,只是結果不再是組成鏈的一部分:

intercalate " something " . reverse $ map reverse list 
+0

非常感謝這個清晰的解釋! – Felix

2

使用.的函數組合意味着函數會有另一個參數。如果你寫了下面的話,它會起作用。

main = print $ (intercalate " something " . reverse . map reverse) list 

這樣一來,list值是括號內構成的功能的參數。

+0

這實際上很有道理。非常感謝! – Felix

3

功能組合物的等價去如下:

main = print (intercalate " something " (reverse (map reverse list))) 
main = print (intercalate " something " ((reverse . map reverse) list)) 
main = print ((intercalate " something " . (reverse . map reverse)) list) 
main = (print . (intercalate " something " . (reverse . map reverse))) list 

,或者通過丟棄不必要的括號:

main = (print . intercalate " something " . reverse . map reverse) list 
main = print . intercalate " something " . reverse . map reverse $ list 

在你嘗試,map reverse list是一個單一表達式,中綴的參數.運算符,它不起作用 - 您只能編寫map reverse函數,然後將整個組合函數應用於list參數。

+0

非常感謝Bergi的回覆,現在有意義! – Felix