2015-01-05 65 views
0

我試圖理解Haskell中的列表,並且我碰到了一些我不確定的東西。是否有可能遍歷一個循環,並在每次迭代中添加一個項目到列表?對於這個問題的目的,我寫了下面的代碼:Haskell通過遞歸將元素添加到列表中

list = [] 
addNumbers 0 = return() 
addNumbers n = 
do 
    print n 
    n : list 
    addNumbers (n-1) 

我認爲這會工作,但它似乎給了錯誤「無法與‘IO’匹配類型‘[]’」。我不太確定爲什麼會出現這個錯誤,因爲用戶沒有要求輸入或輸出。我認爲這可能與「打印n」有關,但如果沒有這一行,它似乎不起作用。

乾杯提前任何幫助

+0

通常在Haskell你會分裂的數字從創建這樣一個列表打印(不純的操作)(純)。如果您只是使用print語句進行調試,則可以使用類似Debug.Trace的方法來欺騙類型檢查器(同樣,僅用於調試目的)。 http://en.wikibooks.org/wiki/Haskell/Debugging#Debug_prints_with_Debug.Trace – MaxGabriel

+0

您將'print'中的'IO' monad和List monad混合在同一個綁定中!請記住'a < - something'只是'something >> = \ a - >'的糖,因此它需要非常特殊的類型。 – AJFarmar

回答

4

這不會做你認爲它確實在Haskell一切都是不可改變的(一旦它被賦予一個值,這個值不能改變)。你可能會試圖做的是:

addNumbers :: Int -> IO [Int] 
addNumbers 0 = return [] 
addNumbers n = do print n 
        ns <- addNumbers (n-1) 
        return (n:ns) 

然後在解釋器,你會得到

ghci> addNumbers 3 
3 
2 
1 
[3, 2, 1] 
ghci> 

仔細注意的addNumbers簽名,它接受一個Int並返回Int列表由IO monad封裝。它必須由IO monad封裝,因爲在IO monad中打印的調用返回(),如果沒有,那麼值將不會被打印。

如果你只是想前置到列表Int的列表,那麼你可以很容易地做到

foo 0 = [0] 
foo n = n:foo (n-1) 
+0

我一直在玩這個,它完美的作品。只是另一個小問題,我試圖添加一個if語句。所以如果這個數字可以被3整除,那它就會被添加到列表中,如果不是,它只需要一個。它似乎不喜歡if語句中的ns < - addNumbers(n-1)。 – Jordan

+0

@Jordan用''if'mod'替換'return(n:ns)'3 == 0然後返回(n:ns)或者返回(尾部ns)''。你不需要在'if'下爲''運行'addNumbers'。 (注意,因爲這可以嘗試從空列表中刪除一個元素) – chi

+0

謝謝chi,有沒有什麼理由我無法在輸出中調用「length」?我認爲這創建了一個列表。但是,如果我從randomusername的代碼中刪除打印並調用「length(addNumbers 3)」,它會給出錯誤。任何想法? – Jordan