2012-03-12 102 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