2011-04-13 28 views
11

我只在哈斯克爾兩天,現在,想知道以下兩個函數定義之間的區別是:語法列表構造/級聯

Prelude> let swap (x1:x2:xs) = x2:x1:xs 
Prelude> swap [1..5] 
[2,1,3,4,5] 
Prelude> let swap' (x1:x2:xs) = [x2] ++ [x1] ++ xs 
Prelude> swap' [1..5] 
[2,1,3,4,5] 

也就是說,是什麼讓X2:X1 :xs不同於[x2] ++ [x1] ++ xs? 請和謝謝。

+2

你是什麼意思不同?它們的指示是相同的,即交換和交換「做同樣的事情。 – augustss 2011-04-13 12:53:28

回答

25

的類型簽名是一個良好的開端:

(:) :: a -> [a] -> [a] 
(++) :: [a] -> [a] -> [a] 

您可以找到這些出在ghci中:type (:):type (++)

正如您從類型簽名中看到的,兩者都用於生成列表。

:運算符用於構造列表(並將它們再次分開以進行模式匹配)。要製作一份清單[1,2,3],您只需使用1 : 2 : 3 : []即可創建清單。 :的第一個元素是要添加到列表前面的項目,第二個元素是列表(也由:構建或由[]表示的空列表)。

++運算符是列表級聯。它需要兩個列表並將它們附加在一起。 [1,2,3] ++ [4,5,6]是合法的,而1 ++ [1,2,3]不是。

+0

它越來越清晰。在第一個列表中,我從一個列表創建了一個列表,而在最下面的一個列表中,我創建了3個列表並將它們連接在一起。這是否意味着最高的那個會更快/更高效? – 2011-04-13 21:49:08

+0

在第一個中,您將通過交換的前兩個元素和相同的尾部創建列表。在第二個例子中,通過將前兩個分開來創建列表,然後將它們構建爲列表並將它們與尾部連接起來。我猜想第一個會更有效率,但我認爲這不是最重要的。第一個比較習慣的Haskell在我看來,所以這就是爲什麼你應該選擇它。 – 2011-04-14 08:20:48

+0

謝謝!在這裏的解釋和今天更多的學習之後,這一切都變得更有意義。 – 2011-04-14 09:28:26

3

這與語法無關。 (:)和(++)只是不同的操作符。 (:)是從元素和另一個列表構造列表的構造函數。 (++)創建一個新列表,即兩個列表的連接。因爲(++)不是構造函數,所以不能在模式中使用它。

現在我們就來語法:符號

[x2] 
您使用是

x2:[] 

速記你真的在第二個例子中這樣做是什麼

(x2:[]) ++ (x1:[]) ++ xs 

因此,當構建一個列表時,你無法避免(:),它是最終的唯一方法。請注意,您必須構建中間列表才能使用(++)。