2011-05-27 21 views
2

我給字符數組並有翻譯爲移動(如下圖所示)哈斯克爾 - 作業 - 連接兩個列表

data Move = N | S | W | E | X 
newtype Moves = Moves [Move] 

createMoves:: [Char]-> Moves 
createMoves (x:xs) = if xs==[] then Moves [createMove(x)] 
         else Moves [createMove (x)] 

createMove:: Char-> Move 
createMove (x) = if x=='N' then N 
       else if x=='S' then S 
       else if x=='W' then W 
       else if x=='E' then      
       else X 

不過,我只有在獲得列表的第一個項目成功。我已經嘗試了許多方法來使createMoves遞歸,但我無法做到。你能指導我嗎?

+0

你應該格式化你的代碼...... – Kru 2011-05-27 16:05:47

+2

函數在Haskell中不需要括號。你應該只寫「createMove x」。 – amindfv 2011-05-27 16:39:26

+2

順便說一下,這個'[Char]'是**不是**數組。它是一個*列表*。 – fuz 2011-05-27 16:46:38

回答

3

您的if語句的分支是相同的,所以它什麼都不做。

編程遞歸函數時,有兩種情況。 基本的一個,你應該聲明createMoves [] = []。 遞歸更復雜一點;基本上,對於每個x,您創建一個移動,該移動是在xs上使用遞歸調用構建的列表的第一個元素。

更簡單的方法是使用map函數。你也可以看看它的實現。 順便說一下,對於createMove,您可以使用模式匹配而不是許多if s。

+0

這就是我想要做的,但它會干擾類型簽名。我想實現這樣說: createMoves :: [字符] - >移動 createMoves(X:XS)=如果XS == [],然後移動[createMove(x)]的 \t \t \t其他createMoves(XS ):移動[createMove(x)] – Annabel 2011-05-27 16:37:42

+0

您遇到類型簽名問題的原因是您要將「移動」類型構造函數放入遞歸函數中。如果沒有出現類型問題,列表將如下所示:移動[N,移動E,移動S]。你只需要移動[N,E,S]。 – amindfv 2011-05-27 16:51:27

+0

用'newtype Moves = [Move]'替換'newtype Moves =移動[移動]',這將簡化您的代碼,並且每次創建移動列表時都不需要構造函數。 – Kru 2011-05-27 17:00:18

1

您的createMoves函數只對它給出的列表中的一個元素進行操作。

嘗試使用map函數。在換句話說,開始你的函數:

createMoves list = Moves (map 

[...]

1

您不妨用逆天(即|),而不是ifthenelse

2

您的問題似乎集中在將xs上的遞歸調用的結果與createMove x的結果相結合。所以,讓我們來介紹一個輔助功能,它將會照顧到這一點!

createMoves:: [Char]-> Moves 
createMoves (x:xs) = if xs==[] then Moves [createMove x] 
         else createHelper (createMove x) (createMoves xs) 

現在,createHelper應該是什麼類型?它的第一個參數是Move,第二個參數是Moves,它應該將第一個參數放在第二個包含的Move列表的前面,並將其重新包裝爲Moves類型的值。爲了獲得在Move是清單,你需要使用模式匹配,就像這樣:

createHelper :: Move -> Moves -> Moves 
createHelper m (Moves ms) = Moves (m:ms) 

這應該做的伎倆,但在Moves構造這一切的匹配,然後重新應用它是一個有點傻,並有可能效率低下。更好的方法是將[Char]逐個轉換爲[Move],並且僅在最後加上Moves構造函數。這導致類似(仍與你最初的想法保持):

createMoves :: [Char] -> Moves 
createMoves cs = Moves (createMoveList cs) 

createMoveList :: [Char] -> [Move] 
createMoveList (x:xs) = if xs == [] then [] else createMove x : createMoveList xs 

createMoveList是經常出現在Haskell,即應用功能(在這種情況下,createMove)每個元素的模式在一個列表中。這是map函數的本質(如果你還沒有的話,我相信你很快就會在課堂上得到它)。

如果使用該功能,您還可以擺脫createMoves在給出空列表時失敗的問題。因此,解決辦法我會去爲:

createMoves :: [Char] -> Moves 
createMoves cs = Moves (map createMove cs) 

createMoves = Moves . map createMove 

但那是另一回事!

+0

很好的回答! +1因爲沒有嘗試修復任何未被破解的內容。 :-) – Rotsor 2011-05-28 08:19:16

0

首先,您應該刪除newtype聲明;如果你想要列表打印,只需要Move類型派生Show

接下來,您可以使用map刪除createMoves函數中的顯式遞歸。爲了將來的參考,您可以在Hoogle上按名稱和類型簽名查找功能。

最後,您可以使用模式匹配來消除所有針對常量的相等性測試。使用Move類型無關例子是

isN :: Move -> Bool 
isN N = True 
isN _ = False 

注意,_字符表示「忽略這個值」。如果尚未涉及模式匹配,那麼守衛可能仍然比嵌套的if更好。