2013-08-25 44 views
3

我是Haskell的新手,我遇到了問題。我需要編寫一個函數,將列表分割成一個列表,列表中出現'分隔'。如何通過刪除特定分隔將列表拆分爲列表(Haskell)

+0

你第一次刺激算法是什麼?你可以先嚐試顯式遞歸或者先解決一個簡單的問題(其中分隔符是單個Char)。 – jev

+0

如果可以用空格替換分隔符,則可以用':'替換分隔符。到目前爲止,你有什麼? – bheklilr

回答

7

我會盡力幫助您開發的如何開發通過遞歸上列出的工作職能的認識。瞭解如何首先以「低級」方式進行操作是很有幫助的,這樣您就可以更好地理解在實際代碼中更常見的「高級」方式中發生的事情。

首先,你必須想想你要使用的數據類型的性質。該列表是在某種意義上遞歸定義的類型的在Haskell的典型的例子:一個列表要麼是空列表[]或它與經由a : list列表合併一些列表元素a。這是唯一的兩種可能性。我們將空列表稱爲基本情況,因爲它是在其定義中未引用自身的情況。如果沒有基本的情況,遞歸永遠不會「谷底」,並會無限期地繼續下去!

,有兩種情況,一個list的定義,這意味着你必須在與列表工作的函數的定義考慮兩種情況。在Haskell中考慮多個案例的規範方法是模式匹配。 Haskell語法提供了許多方法可以做到模式匹配,但我只使用基本的case表達現在:

case xs of 
    [] -> ... 
    x:xs' -> ... 

就是這兩種情況下,一個必須考慮的列表。第一個匹配文字空列表構造函數;第二個元素與元素添加構造函數:相匹配,並且還將兩個變量xxs'綁定到列表中的第一個元素以及包含其餘元素的子列表。

如果你的函數傳遞一個是第一種情況相匹配列表中,那麼你知道,無論是最初的名單是空的,或者您已完成列表中一路過去的最後一個元素的遞歸。無論哪種方式,都沒有更多的列表要處理;你要麼完成了(如果你的調用是尾遞歸的),或者你需要將你的答案構造的基本元素傳回給調用這個元素的函數(通過返回它)。如果你的答案是一個列表,那麼基本元素通常是空列表[]

如果你的函數傳遞一個第二情況下匹配列表,那麼你知道它是通過一個非空列表,而且你有一對夫婦必然有用值的新變量。根據這些變量,你需要決定兩件事情:

  1. 我怎麼做我的一個元素算法的一步,假設我有從列表其餘執行了正確的答案?
  2. 如何將該步驟的結果與在列表的其餘部分執行結果相結合?

一旦你想出了這些問題的答案,你需要構造一個表達式來組合它們;爲列表的其餘部分獲取答案只是在列表的其餘部分調用遞歸調用,然後您需要執行第一個元素和組合的步驟。

這裏有一個簡單的例子,發現一個列表

listLength :: [a] -> Int 
listLength as = 
    case as of 
    [] -> 0     -- The empty list has a length of 0 
    a:as' -> 1 + listlength as' -- If not empty, the length is one more than the 
           -- length of the rest of the list 

這裏的長度是另外一個例子,從列表中刪除匹配的元素現在

listFilter :: Int -> [Int] -> Int 
listFilter x ns = 
    case ns of 
    [] -> []       -- base element to build the answer on 
    n:ns' -> if n == x 
       then listFilter x ns'  -- don't include n in the result list 
       else n : (listFilter x ns') -- include n in the result list 

,你問的問題是多一點點很困難,因爲它涉及次要的「列表匹配」遞歸以識別列表中基本遞歸的分隔符。向遞歸函數添加額外參數有時會很有幫助,以便保存關於問題所在位置的額外信息。它也可能模式匹配在同一時間兩個參數通過把它們放在一個元組:

case (xs, ys) of 
    ([] , [] ) -> ... 
    (x:xs', [] ) -> ... 
    ([] , y:ys') -> ... 
    (x:xs', y:ys') -> ... 

希望這些提示將幫助您對您的問題取得了一些進展!

+0

很好的解釋,很容易理解像我這樣的新手 – keduadoi

3

讓我們看看問題是否可以明顯減少。

假設splitList是用xs調用split和ys作爲分隔符的。如果xs爲空,問題是最小的,那麼問題的答案是什麼?在這裏得到正確的答案很重要,因爲歸納解決方案取決於這個決定。但我們可以稍後做出這個決定。

好的,所以對於可縮減的問題,列表xs不是空的。所以,它至少有一個head元素h和較小的問題t,列表的尾部:你可以匹配xs @(h:t)。如何獲得較小問題的解決方案?那麼,splitList可以通過函數的定義來解決這個問題。所以現在的技巧是找出如何爲更大問題(h:t)構建解決方案,當我們知道解決較小問題zs = splitList t ys的解決方案時。這裏我們知道zs是列表[[a]]的列表,並且因爲t可能是最小的問題,所以zs很可能是最小問題的解決方案。所以,無論你用zs做什麼,即使是解決最小的問題,它也必須是有效的。

splitList [] ys = ... -- some constant is the solution to the smallest problem 
    splitList [email protected](h:t) ys = let zs = splitList t ys 
          in ... -- build a solution to (h:t) from solution to t 
+0

tks,所以這是首先想到如何編寫遞歸函數的方法 – keduadoi

1

我不知道如何對它進行測試。任何人告訴我如何寫一個.hs文件的函數,並使用winGHCi來運行此功能?

WinGHCi自動關聯.hs文件,所以只需雙擊該文件並啓動ghci。使用你最喜歡的編輯器對文件進行一些更改後,你可以使用ghci中的:r命令來重新加載文件。

要在修改拼寫錯誤,鍵入錯誤並確保正確縮進後測試程序,請嘗試調用您使用不同輸入定義的函數(或使用QuickCheck)。備註Maybe定義爲Just xNothing。您可以使用fromMaybe來提取x(併爲Nothing情況提供默認值)。

也嘗試確保模式匹配是詳盡的。