2010-05-20 57 views
2

我想弄清楚從here工作(我明白flatten,插入和foldr)如何確切treeort。問題了解在Haskell tr​​eesort

我想在treesort中正在做的是對列表上的每個元素應用插入,從而生成一棵樹並將其展平。我在這裏無法克服的唯一問題是列表(即函數的參數)隱藏的地方(因爲除了函數類型聲明外,它沒有被寫入任何地方作爲參數)。

還有一件事:由於點運算符是函數組合,爲什麼當我更改時出錯:treesort = flatten . foldr insert Leaftreesort = flatten(foldr insert Leaf)

回答

8

什麼在treesort正在做正在爲列表中的每個元素應用插入,從而生成一棵樹,然後展開它。

沒錯。

[哪裏列表隱藏?]

在函數式語言,你不必給函數類型的值的參數。例如,如果我寫

f = concat . map (map toUpper) 

我得到類型爲[[Char]] -> [Char]的函數。即使在定義方程中沒有參數,這個函數也會期待一個參數。 這是正是,如果我寫了

f strings = (concat . map (map toUpper)) strings 

由於點運算符是函數組合一樣,爲什麼錯了改變f . gf (g)

它們並不意味着同樣的事情。當每個應用於x時會發生什麼?

(f . g) x = f (g x) 

(f (g)) x = (f g) x 

你可以看到不同的應用程序相關聯,並f. gf g不同。

這是一個類型錯誤,因爲foldr insert Leaf是從列表到樹的函數,並且flatten意味着應用於單個樹而不是函數。

+0

我不確定'f strings = ...和'f = \ strings - > ...'是同一件事情。 – ony 2010-05-20 05:34:59

+1

@ony:和['a「,」b「]」和「a」一樣:「b」:[]';他們是編寫相同價值的兩種不同方式。 – 2010-05-20 05:53:18

6

先回答你的最後一個問題,因爲.是一個函數合成運算,它有兩個功能(在這種情況下flattenfoldr insert Leaf)你得到一個錯誤。如果你想重寫代碼,而無需使用.,你需要創建一個函數,它的一些參數:

-- // Pass the 'list' to the first function and the 
-- // result of the call to the second function 
treesort list = flatten (foldr insert Leaf list) 

這也解釋了其中list參數躲藏。在編寫功能,您無需明確寫入參數,因爲表達式f . g的結果是一個函數,需要一些參數,調用g然後調用f

-- // function composition.. 
composed = f . g 
-- // ..is equivalent to declaring a function: 
composed x = f (g x) 
+0

嚴格地說,在鏈路的treesort函數接受一個列表參數,而不是一棵樹,所以「樹」可能不是變量名的最佳選擇。 – 2010-05-20 02:03:26

+0

@彼得:是的,我也意識到這一點 - 感謝修正。 – 2010-05-20 02:10:09

1

有時候,只要你不熟悉無意義的風格,在心理上進行epsilon轉換是有用的。

如果f是與功能類型的表達式,那麼就可以將其轉換爲 。\ E - >(F)在線

而且,如果我們有像

a = \e -> (f) e 

我們總能定義安全地把它改寫爲

a e = (f) e 

因此

treesort = flatten . foldr insert Leaf 

相同

treesort list = (flatten . foldr insert Leaf) list