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