2015-01-17 1 views
0

Я пишу программу Haskell. Более продвинутые функции позже, но пока я застреваю в файле чтения. Я знаю, что в нем много потоков, но, насколько я вижу, все решения основаны на петлях. Мне нужно прочитать из txt-файла с 3 строками. и сохранять содержимое этих 3 строк в 3 отдельных переменных для дальнейшего использования, поэтому решение на основе петли не только не является необходимым, но и проблематичным (с сохранением на 3 разных переменных). Я немного искал, нашел некоторые примеры, пытался что-то построить из них, но этот язык кажется настолько странным, что я не могу понять, почему некоторые модификации работают, а некоторые нет.Рединг 3 строки из файла - Haskell

Прежде всего, рабочий код:

import System.IO 

main :: IO() 
main = do 
    inh <- openFile "input.txt" ReadMode 
    outh <- openFile "output.txt" WriteMode 
    mainloop inh outh 
    hClose inh 
    hClose outh 

mainloop :: Handle -> Handle -> IO() 
mainloop inh outh = do 
inp1 <- hGetLine inh 
inp2 <- hGetLine inh 
inp3 <- hGetLine inh 
putStrLn (inp3) 

Этот код считывает первый, затем вторая, затем третья строка из файла, сохраняет каждый в соответствующие переменный, а затем помещает inp3 на экране. Тем не менее, мне не нужно печатать его, просто сохраняйте его на 3-х переменных для дальнейшего использования, но без линии печати программа не работает, компилятор говорит, что «последний оператор в блоке do должен быть выражением». Если я, однако, хочу напечатать больше строк, чтобы увидеть, правильно ли работает чтение, и добавить еще putStrLn (для inp1 и inp2), он не будет компилироваться. Например, после добавления строки «putStrLn (inp1)» сразу после строки с получением inp1 она не будет компилироваться и говорит «Ошибка Parse в putter putStrLn, возможно, вызвана отсутствующим« сделать »? Я просто начинаю с Haskell, поэтому Вероятно, это очевидно, но я понятия не имею, что.

Существует также вторая проблема. Эта программа читается из input.txt. Я хочу, чтобы она запрашивала имя, дожидалась, когда человек наберет, а затем откройте его. Я полагал, что это будет что-то вроде

putStrLn "Type name" 
name <- getLine 
inh <- openFile name ReadMode  

но он не работает. Я буду очень благодарен за любой вклад, который может помочь мне. как ни странно, в примере, приведенном в http://en.wikibooks.org/wiki/Haskell/Libraries/Solutions/IO использует что-то подобное, и это Compi ле без проблем, но мой не будет. Любые предложения?

+1

Почему бы вам не вернуть свои строки вместо этого? Например. 'mainloop :: Handle -> Handle -> IO (String, String, String); ....; inp3 <- hGetLine inh; return (inp1, inp2, inp3) '. – chi

+0

Потому что я глуп и не знаю Хаскелла достаточно хорошо. ;) Большое спасибо, Любые идеи о вводе имени файла? – desf

+1

Вы не должны пытаться обучать в двух вопросах, которые касаются только касательно. Просто создайте новый вопрос. Кроме того, 'mainLoop inh = liftA3 (,,) a a a где a = hGetLine inh'. – user2407038

ответ

1

Таким образом, проблема в том, что G отказываются компилировать:

mainloop :: Handle -> Handle -> IO() 
mainloop inh outh = do 
    inp1 <- hGetLine inh 
    inp2 <- hGetLine inh 
    inp3 <- hGetLine inh 

право?

Это на самом деле очень разумно, вы думаете о (плохих) императивных терминах, как если бы ваш inp # был глобальными переменными, которые вы могли бы использовать в другой функции после их инициализации в mainloop ... Но это не так : INP1, INP2 и inp3 только локальные привязки, которые были введены и могут быть использованы только в этом делать-блок в mainloop так, когда последняя строка:

inp3 <- hGetLine inh 

Очевидно, что есть ошибка, так как вы выиграли» t быть в состоянии использовать этот inp3 в любом месте (вы находитесь в конце do-block), поэтому GHC сообщает вам, что последняя строка вашего блока do должна быть выражением типа putStrLn inp3, а не эффектом ион.

Теперь должно быть ясно, что ваша функция mainloop на самом деле читать строки, но сразу же потерять их, если вы хотите использовать их в вызывающем вы вернуть их return (inp1, inp2, inp3), например (что является выражением так что ваш GHC будет довольны вашим блоком do-block). Конечно, Haskell является королем абстракции, повторяя одну и ту же строку 3 раза и давая 3 бесполезных имени временной переменной - это немного анафема ...Другие предложения сделать то же самое без повторений и необходимости придумывать бесполезные имена будут:

mainLoop inh = liftA3 (,,) a a a where a = hGetLine inh 

, который будет возвращать триплет или:

mainLoop inh = replicateM 3 (hGetLine inh) 

, который будет возвращать список 3-х элементов ... Но на данный момент я бы, вероятно, не создал функцию только для [l1,l2,l3] <- replicateM 3 (hGetLine inh).

Смежные вопросы