2015-02-09 48 views
1

我對Haskell來說比較新,我很想找出實現Haskell的span函數的方法。然而,我的問題比這更一般,因爲我不知道如何讓一個函數返回包含我想要的元素的列表或包含元組列表的列表。我和列表,如清單問題:Haskell的跨度函數

[[1],[2]] 

的是,我不能讓功能列表清單中的元素添加到第一個列表。我只知道如何將另一個列表附加到列表中。

總之,如果你向我解釋如何實現span函數,這一切應該有希望清楚地告訴我。

+1

你看過實際的實現嗎? http://haddocks.fpcomplete.com/fp/7.8/20140916-162/base/src/GHC-List.html#span – 2015-02-09 10:28:34

+1

嗯。如何編寫'addToFirstInList :: a - > [[a]] - > [[a]]'是不是真正的問題?畢竟,你談論的是「列表清單」,而「span」則返回列表的列表。 – Zeta 2015-02-09 10:32:37

+2

如果你的問題是關於添加一個元素到列表的第一個列表,然後說實話,我認爲你應該閱讀列表(推薦真實世界Haskell /學習你一個Haskell)。如果它真的關於'span',那麼你應該編輯它以更好地表明你的意圖 – joozek 2015-02-09 10:33:35

回答

1

所以我覺得什麼你的意思是,你知道如何遞歸做類似

foobar :: [x] -> [y] 
foobar ( []) = [] 
foobar (x:xs) = {- ...stuff... -} : foobar xs 

追加到一個列表,但你不知道怎麼做,與2名名單:

foobar :: [x] -> ([y], [z]) 
foobar (x:xs) = ??? 

在一般情況下,當結果不是一個名單,但一些包含列表,你最終會做這樣的事情:

foobar :: [x] -> ([y], [z]) 
foobar (x:xs) = 
    let 
    y = {- whatever -} 
    z = {- whatever -} 
    (ys, zs) = foobar xs -- The recursive call 
    in (y:ys, z:zs) 

同樣適用如果說,結果是一元行動

foobar :: [x] -> IO [y] 
foobar (x:xs) = do 
    y <- {- whatever -} 
    ys <- foobar xs 
    return (y:ys) 

注意,這迫使該功能不能偷懶。

+0

哦,我明白了!我想我現在明白了!我通常不會在StackOverflow上提出這樣簡單的問題,但我在網上找不到任何幫助......我認爲隨着我進一步閱讀「真實世界Haskell」這本書,它也會變得更加清晰。謝謝! – Prince 2015-02-09 17:37:28

0

一般模式我想你會想在這裏用的是以下幾點:

span :: (a -> Bool) -> [a] -> ([a], [a]) 
span pred [] = ([], []) 
span pred (x:xs) = if pred x then _ else _ -- fill in the blanks 
    where (prefix', suffix') = span pred xs 

有兩個非顯而易見的事情出現了。首先,請注意where條件中的模式匹配。這意味着我們是:

  1. 調用span pred xs,它產生一對列表;
  2. 這一對的模式匹配;
  3. 分別命名配對prefix'suffix'中的第一個和第二個元素。

我懷疑,第2步,遞歸調用的結果模式匹配,你可能不知道。

第二個非顯而易見的事情是遞歸。這是一件棘手的事情,因爲,爲了解決遞歸問題,你需要假設你已經解決了這個問題,但是對於「錯誤的」論點 - 如果你還沒有解決它,想象一下你自己採取的一個艱難的步驟!但關鍵是這樣的:

  • 想象一下你其實已經解決了這個問題,但對於名單的。這就是prefix'suffix'變量包含的內容:正確的解決方案,但對於錯誤的列表 - 您實際嘗試解決的問題的尾部。
  • 考慮到(非)解決方案,您如何重複使用它以達到您的問題的正確解決方案?