2010-06-26 101 views
2

這個問題與這個Function Composition VS Function Application有關,由antal s-z回答。Haskell類型錯誤從函數應用到函數組合

你如何得到這個?

map has type (a -> b) -> [a] -> [b] 
head has type [a] -> a 
map head has type [[a]] -> [a] 

爲什麼下面的代碼有函數組合的類型錯誤?

test :: [Char] -> Bool 
test xs = not . null xs 

getMiddleInitials :: [String] -> [Char] 
getMiddleInitials middleNames = map head . filter (\mn -> not . null mn) middleNames 

,但這並沒有錯誤類型

getFirstElements :: [[a]] -> [a] 
getFirstElements = map head . filter (not . null) 

它是一個必須以利用函數組合寫點免費功能? 我還是不太瞭解函數組合的用法。

請幫忙。 謝謝。

回答

3

你的錯誤在這裏更高的優先級其實是非常簡單的。如果您還記得my answer to your last question的最後一部分,則.運算符具有比更高的優先級,但功能應用程序的除外。因此,考慮你的例子

test :: [Char] -> Bool 
test xs = not . null xs 

這被解析爲test xs = not . (null xs)。當然,null xs的類型爲Bool,並且您無法撰寫布爾值,因此會出現類型錯誤。因此,你可以讓你的例子像這樣工作:

test :: [Char] -> Bool 
test xs = (not . null) xs 

getMiddleInitials :: [String] -> [Char] 
getMiddleInitials middleNames = 
    (map head . filter (\mn -> (not . null) mn)) middleNames 

當然,這樣寫它是不尋常的,但它會正常工作。

不,除了無點式以外還有其他功能組合的用途。一個例子是對某些事情使用函數合成(,例如參數爲mapfilter),但指定其餘部分。舉例來說,利用這個人爲的例子:

rejectMapping :: (a -> Bool) -> (a -> b) -> [a] -> [b] 
rejectMapping p f = map f . filter (not . p) 

這部分是點免費(not . p,例如,我們離開的最後一個參數),但部分點滿(存在pf)。

+0

真的不明白rejectMapping例子的最後部分。 – peterwkc 2010-06-27 03:07:07

+0

哪部分你不明白?它背後的動機,它應該做什麼,或者它是如何工作的?它只使用你已經看過的東西,所以如果你仔細想想,你應該可以遵循它! – 2010-06-27 03:28:51

4

這只是因爲功能應用x y比組成x . y

test :: [Char] -> Bool 
test xs = (not . null) xs 
-- # ^  ^

getMiddleInitials :: [String] -> [Char] 
getMiddleInitials middleNames = (map head . filter (\mn -> (not . null) mn)) middleNames 
-- #       ^      ^  ^^