Haskell: как использовать haskeline и записать в файл в одной программе - PullRequest
2 голосов
/ 19 марта 2019

Я написал программу на Haskell, которая создает вкладку гитары в виде txt-файла в текущем каталоге.Он получает строку аккордов от пользователя, а затем создает правильный вывод и записывает его построчно в файл.

Я не смог использовать клавишу возврата на входе, когда использовал getLineпотому что это выведет на экран кучу бредов.

Я пытаюсь использовать haskeline, чтобы исправить это, и тем временем я закомментировал основную часть моего основного метода, чтобы каждое изменение требовало меньше редактирования(каждая команда, которую я закомментировал в 'main', имеет тот же тип, что и единственная команда, которую я сохранил, поэтому, если я смогу заставить работать эту упрощенную версию, все должно работать).По сути, мне нужно иметь возможность получать входные данные от пользователя с помощью haskeline, но затем мне также нужно выполнить некоторые команды «побочных эффектов» в моем блоке «do» после этого.

ЯЯ новичок в Хаскеле, и я не до конца понимаю, что разрешено и почему не разрешено.Вот упрощенная версия моей программы:

import Data.List
import System.Console.Haskeline

main = runInputT defaultSettings loop
 where
   loop :: InputT IO ()
   loop  = do
     name <- getInputLine "Enter name of song: "
     case name of
       Nothing -> return ()
       Just songName -> return ()
     chords <- getInputLine "Enter chords to be tabified "
     case chords of
       Nothing -> do outputStrLn $ "No chords entered. Exiting."
       Just chords -> do
                        writeFile "./test.txt" "did it work?"
                        return ()

Я получил весь этот синтаксис прямо из руководства по Haskeline.Я попытался запустить его без внесения каких-либо изменений в первую очередь, и это сработало, поэтому я знаю, что все правильно, за исключением последних 3 строк, которые я редактировал, где у меня есть блок "do" и я пытаюсь вызвать "writeFile" перед "return () ".

Я знаю, что тип" loop "должен быть InputT IO (), чтобы использовать getInputLine (версия getLine для haskeline), но я не знаю, как это сделать"«Побочные эффекты», такие как одновременная запись в файл.

Когда я пытаюсь загрузить свой проект в ghci, я получаю следующую ошибку:

error:
-Couldn't match type 'IO' with 'InputT IO'
 Expected type: InputT IO ()
   Actual type: IO ()
- In a stmt of a 'd' block: writeFile "./test.txt" "did it work?"
  In the expression:
    do { writeFile "./test.txt" "did it work?";
         return () }
  In a case alternative:
    Just chords
      -> do { writeFile "./test.txt" "did it work?";
              return () }

Failed, modules loaded: none.

Ответы [ 2 ]

4 голосов
/ 19 марта 2019

Поскольку InputT IO является экземпляром MonadIO, вы можете запустить любое действие ввода-вывода, подняв его до действия InputT IO, используя

liftIO :: IO a -> InputT IO a

Действительно, это стандартный способ "запустить IO "в moands, которые поддерживают IO, но не IO.

4 голосов
/ 19 марта 2019

InputT является экземпляром MonadTrans, поэтому

Just chords -> lift $ do

РЕДАКТИРОВАТЬ:

lift находится в Control.Monad.Trans.Class .(Наконечник шляпы: Джон Перди )

...