Haskell ReplicateM IO - PullRequest
       42

Haskell ReplicateM IO

3 голосов
/ 12 марта 2012

Я пытаюсь создать функцию, которая позволяет пользователю вводить список строк.Функция принимает длину и позволяет пользователю вводить длину на 1 строку больше.Затем каждая строка проверяется на ту же длину, что и исходная строка.Однако у меня есть несколько проблем, и я не могу найти решение.

Проблемы заключаются в том, что я могу ввести больше строк со счетчиком-1, а длина не рассчитывается так, как я ожидал ... например, если я введу ["12", "13"], а затем ["121 "," 13 "] выдается ошибка, хотя они имеют одинаковую длину!

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

Строка имеет тип String.

readLn дает ошибку разбора.

1 Ответ

5 голосов
/ 12 марта 2012

Мне кажется, что вы запутались в разнице между получением строки как 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"]без ошибок.

...