2012-03-12 70 views
3

我试图创建一个允许用户输入字符串列表的函数。该函数获取长度并允许用户输入长度为1的线。然后检查每一行以确保它与原始行的长度相同。但是,我遇到了一些问题,并且找不到解决方案。例如,如果我输入[“12”,“13”],然后输入[“121”],那么输入的行数就会大于count-1行, ,“13”]给出了错误,尽管它们的长度相同!Haskell ReplicateM IO

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 

行是字符串类型。

readLn给出了一个分析错误。

+0

您的代码对我来说工作正常(除了if-then-else块的缩进问题)。 – 2012-03-12 11:24:20

+0

作为澄清,第一行输入意味着是一个数字,告诉你有多少其他线?或者这个数字实际上是基于你写在这里的第一行的长度(字符数)? – huon 2012-03-12 11:25:46

+0

字符串'[“12”,“13”]和'[“121”,“13”]'不具有相同的长度。后者比第一个字符多一个字符。你想阅读字符串或字符串列表吗? – danr 2012-03-12 11:29:07

回答

5

对我来说,听起来像你对将行作为String和读取/解析一行输入作为自定义类型之间的区别感到困惑。您正在使用getLine,它始终返回用户输入的String。比较:

Prelude> fmap length getLine 
["12","13"] 
11 
Prelude> length "[\"12\",\"13\"]" -- explanation of the 11 
11 
Prelude> fmap length (readLn :: IO [String]) 
["12","13"] 
2 
Prelude> length ["12", "13"] -- explanation of the 2 
2 

作为展示的一样,你可能想使用readLn,它首先得到一个线路输入,然后用read分析它。

-- defined in the Prelude 
readLn = do 
    s <- getLine 
    return (read s) 

如果我修改代码以包括以下进口和定义:

import Control.Monad 
type Line = [String] 

...并呼吁readLn而不是getLine,那么我就可以键入文字线["12","13"]["121","13"]没有错误。

+0

感谢您的解释,我现在看到 - 尽管我的类型Line = String,并且我无法将其更改为[String],因为它在我定义的各种其他函数中使用。所以当在这种情况下使用readLn时,会返回一个解析错误 – gdrules 2012-03-12 11:45:16

+0

(Prelude.readIO:no parse) – gdrules 2012-03-12 12:00:31

+1

@gdrules:改变你的其他功能。或者添加一些胶水代码。 – rampion 2012-03-12 13:27:44