2013-01-09 34 views
1

要從GHCi中的列表中去掉最後一個項目,我可以反轉列表,取出尾部,然後再將其反向。例如,讓功能組合工作不同嗎?

reverse(tail(reverse([1,2,3,4]))) 

由於有相當多的支架存在的,我想我會改變其使用功能組成代替。但是,當我嘗試這個時,我得到以下錯誤。

Prelude> reverse . tail. reverse [1,2,3,4] 

<interactive>:2:17: 
    Couldn't match expected type `a0 -> [a1]' with actual type `[a2]' 
    In the return type of a call of `reverse' 
    Probable cause: `reverse' is applied to too many arguments 
    In the second argument of `(.)', namely `reverse [1, 2, 3, 4]' 
    In the second argument of `(.)', namely 
     `tail . reverse [1, 2, 3, 4]' 

我認爲,這意味着它不喜歡作曲reverse [1,2,3,4],所以我試圖把它周圍的括號,但它給了我同樣的錯誤。

Prelude> reverse . tail. (reverse [1,2,3,4]) 

<interactive>:3:18: 
    Couldn't match expected type `a0 -> [a1]' with actual type `[a2]' 
    In the return type of a call of `reverse' 
    Probable cause: `reverse' is applied to too many arguments 
    In the second argument of `(.)', namely `(reverse [1, 2, 3, 4])' 
    In the second argument of `(.)', namely 
     `tail . (reverse [1, 2, 3, 4])' 

但是,如果我做了以下它能正常工作。

Prelude> let f = reverse . tail . reverse 
Prelude> f [1,2,3,4] 
[1,2,3] 

這是什麼原因導致這個錯誤,爲什麼讓綁定停止發生?

+0

只需提一下,init函數就可以完成這項工作。 – zurgl

+0

@zurgl我知道,這只是我遇到的問題的一個例子;) –

回答

8

當你看到的.類型,你會發現,它預計它的兩個操作數是函數(適合的類型,以便他們可以組成)

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

現在的功能應用比任何綴更高的優先級運營商因此

Prelude> reverse . tail . reverse [1,2,3,4] 

成爲

Prelude> reverse . tail . (reverse [1,2,3,4]) 

當您嘗試應用構圖時,它有錯誤的類型。爲了使作文正確無誤,您必須明確地給出作文比作業應用更高的優先順序,您可以通過提供明確的括號來完成作業。

Prelude> (reverse . tail . reverse) [1,2,3,4] 

這種解決方案的工作原理,但haskellers仇恨使用括號。這裏有另一個運算符$,它可以將你保存在這些地方,使你的代碼比使用括號更可讀。 當你看到的$

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

你可以清楚地看到,它的precendence(0)小於寫作的類型(9),它給你你想要的效果。您可以降低上一個函數應用程序的優先級或用$替換函數組合。

Prelude> reverse . tail . reverse $ [1,2,3,4] 
Prelude> reverse . tail $ reverse [1,2,3,4] 
Prelude> reverse $ tail $ reverse [1,2,3,4] 

這是完全沒有作爲$第一操作數是一個函數等僅僅是一個正確的類型的值。

4

let情況下的功能是由與.然後列表被指定作爲參數的函數組合物的結果:

(reverse . tail . reverse) [1,2,3,4] 

在其他情況下列表中給出作爲參數reverse和該結果被試圖與其他一些功能可以由:

reverse . tail . (reverse [1,2,3,4]) 

由於由reverse [1,2,3,4]返回的反向列表不是一個函數,用它作爲對的參數導致類型錯誤。