2017-02-15 24 views
3

Я хочу прочитать ввод как 12 34 56 в три целых числа, используя Haskell.Как читать три последовательных целых числа от stdin в Haskell?

Для одного целого можно использовать myInteger <- readLn. Но в этом случае, я не нашел ни одного решения, за исключением одного из первого чтения строки, а затем заменить все пробелы с ,, (используя что-то вроде:

spaceToCommas str = 
    let repl ' ' = ',' 
     repl c = c 
    in map repl str 

) и затем вызвать read '[' ++ str ++ ']', который чувствует себя очень хаком. Кроме того, это не позволяет мне заявить, что я хочу прочитать три целых числа, он попытается прочитать любой количество целых чисел от stdin.

Должен быть лучший способ.

Обратите внимание, что я хотел бы получить решение, которое делает не полагаться на внешние пакеты. Использование, например, Parsec, конечно, здорово, но этот простой пример не должен требовать использования полноценной рамки Parser Combinator, верно?

+0

Почему бы не просто вызвать 'readLn' 3 раза в блоке do? Или используйте карту с побочными эффектами, карту в диапазоне длины-3 и вызовите 'readLn' внутри функции. Это вернет список из 3 целых чисел. – Carcigenicate

+0

Вы хотите прочитать 3 целых числа из одной строки? Вход обычно буферизируется по строке - что, если в одной строке есть 4 целых числа? Что делать, если их всего 2? – Carl

+0

О, вы хотите прочитать одну строку? Почему бы просто не прочитать это, а затем разбить на пробелы? – Carcigenicate

ответ

4

Что о преобразовании строки как:

convert :: Read a => String -> [a] 
convert = map read . words 

words разделяет данную строку в список строк («слова»), а затем мы выполняем read на каждом элементе, используя map.

и, например, использовать его как:

main = do 
    line <- getLine 
    let [a,b,c] = convert line :: [Int] in putStrLn (show (c,a,b)) 

или, если вы, например, хотите, чтобы прочитать первые три элемента и не заботятся об остальном (да это, по-видимому, требует супер -creativity навыки) :

main = do 
    line <- getLine 
    let (a:b:c:_) = convert line :: [Int] in putStrLn (show (c,a,b)) 

Я здесь вернулся кортеж, который поворачивается на одно место вправо, чтобы показать синтаксический анализ делается.

+0

Это не читает 3 целых числа от stdin, это просто захватывает строку, пытается ее прочитать и с ошибкой совпадения с шаблоном, если не существует ровно трех. («Кроме того, это не позволяет мне утверждать, что я хочу читать три целых числа, он попытается прочитать любое количество целых чисел из stdin».) – user2407038

+0

@ user2407038: нет, он сам по себе не пытается прочитать все это с тех пор, map' является ленивым (и 'fx' на элементе' map' тоже ленив), и, кроме того, с небольшим количеством * творчества * вы могли бы, конечно, реализовать сценарии с двумя, четырьмя или произвольным количеством целых чисел :) , –

+0

Как правильно использовать это в шаблоне?При попытке использовать 'case convert line of', я всегда получаю ошибку' *** Exception: user (Prelude.readIO: no parse) ' – Qqwy