2012-03-12 106 views
3

我的代碼:Haskell的IO遞歸

read :: IO [Line] 
read = do 
    line <- getLine 
    let count = length line 
    line2 <- getLine 
    if (length line2 /= count) 
    then error "too long or too short" 
    else read 

我想要做的是,根據用戶需要 輸入長度爲1的多個行的第一行的長度,也如果任何這些線不具有相同的長度 作爲原線,將顯示一個錯誤消息。

現在我的代碼僅僅是一個無限循環,因爲我不能完全弄清楚 如何輸入長度-1多行。對此的一些指導將不勝感激。

編輯:行是String類型

+0

的原因,你的代碼是一個無限循環,是因爲你允許它停止的唯一方法是與錯誤。否則,它將一直跟隨if語句的另一個分支並一次又一次地遞歸。 – 2012-03-12 18:23:09

回答

5

您可以使用replicateM複製的動作設定的次數和收集的結果。在你的情況下,行動是抓住一條線,測試它的長度,如果它是無效的錯誤。所以,你可以使用像下面這樣來完成你的工作:

import Control.Monad (replicateM) 

read :: IO [Line] 
read = do 
    line <- getLine 
    let count = length line 
    lines <- replicateM (count-1) $ do 
    line <- getLine 
    if length line /= count 
    then fail "too long or too short" 
    else return line 
    return $ line : lines 
+0

謝謝! ReplicateM看起來不錯,但似乎停止在必要的時候它不(它將會在計數1極限!) – gdrules 2012-03-12 08:53:34

+2

replicateM完美的作品,如果有問題,它可能在你的代碼的其餘部分。當標準的簡單代碼似乎完全失敗時,這是合理的地位:不要責怪標準函數和在自己的代碼中尋找錯誤。如果您仍然無法找到您的錯誤,請將代碼展示給一些經驗豐富的Haskeller,在此處或#haskell。如果他們仍然無法找到錯誤,現在該開始懷疑標準庫了。 – Jedai 2012-03-12 09:16:38

+0

我猜,只是上面的代碼看起來好像沒什麼問題,我會繼續調整它,看看我能找到一個解決...謝謝 – gdrules 2012-03-12 09:56:13