2014-10-29 63 views
1

我有一個列表,例如[1,2,3,4,5],我必須複製列表中的每個元素以形成像[1,1,2,2, 3,4,4,5,5]。在列表中複製元素

作爲一個提示,我們引用了concat函數,它將列表列表變爲單列表。但要嘗試理解你如何更好地在Haskell中做這件事,我試圖手動完成。這裏是我的嘗試:

duplicate :: [a] -> [a] 
duplicate [] = [] 
duplicate (x:xs) = x : (x:xs) duplicate xs 

隨着錯誤消息:

Couldn't match expected type `((a0 -> Bool) -> [a0] -> [a0]) 
            -> [a] -> [a]' 
       with actual type `[a]' 
    The function `x : xs' is applied to two arguments, 
    but its type `[a]' has none 
    In the second argument of `(:)', namely `(x : xs) myTakeWhile xs' 
    In the expression: x : (x : xs) myTakeWhile xs 
Failed, modules loaded: none. 

我的思維方式是你負面因素列表的頭整個列表,然後遞歸調用尾部的功能這份名單。例如,在僞代碼:

duplicate [1, 2, 3] 

1 : [1, 2, 3] duplicate [2, 3] 

2 : [2, 3] duplicate [3] 

3: [3] duplicate [] 

return list [1, 1, 2, 2, 3, 3] 

這是處理這個問題和我在哪裏,我試圖去錯語法的慣用方式是什麼?我不是在尋找替代的,更高效的代碼解決方案,我只是試圖習慣解決問題的功能性方式,而不是尋求事物的必要方式。

謝謝!

+0

'x y'總是意味着'將函數'x'應用於參數'y''。在'[1,2,3]函數'中,'[1,2,3]'不是函數,因此類型錯誤。 – 2014-10-29 13:25:57

+0

您的想法是正確的,但是您錯誤地應用了該功能。代碼,因爲它試圖查看列表作爲您通過'myTakeWhile'和列表的函數。也許,先複製尾巴,然後再追加兩次。 – 2014-10-29 13:29:05

+0

myTakeWhile是一個複製錯誤,試圖遞歸調用重複。已編輯。 – Bradley 2014-10-29 13:42:24

回答

3

你要找的定義是:

duplicate :: [a] -> [a] 
duplicate [] = [] 
duplicate (x:xs) = x : x : duplicate xs 

由於:是右結合的操作,你可以讀到最後的選擇是

duplicate (x:xs) = x : (x : (duplicate xs)) 

duplicate (x:xs) = (:) x ((:) x (duplicate xs)) 

請注意,[1, 2, 3]只是的簡稱210,當duplicate應用於[1, 2, 3]時,使用第二個替代方案,因爲它匹配x : xs(即x = 1xs = 2 : 3 : [])模式。您希望結果從頭開始兩次(這是定義的x : x : ...部分),並繼續使用重複的尾部(... : duplicate xs部分)。

+0

所以我的思維方式起作用了!只是一點點的語法,謝謝! – Bradley 2014-10-29 13:32:08

+0

@Bradley我真的很希望Haskell的列表語法不會讓那些想要學習Haskell的人感到困惑:/ – 2014-10-29 13:33:43

+0

Haskell的學習曲線非常龐大,尤其是對那些在命令式語言中出現的人。我發現我花了大部分時間來弄清楚如何用語法正確的方式來表示我想要的東西 – Bradley 2014-10-29 13:39:31