Haskell:如何使用haskeline并在同一程序中写入文件

时间:2019-03-18 21:04:53

标签: haskell io functional-programming monads haskeline

我用Haskell编写了一个程序,该程序在当前目录中将吉他选项卡构建为txt文件。它从用户那里获取和弦字符串,然后构建正确的输出并将其逐行写入文件。

使用getLine时,我无法在输入中使用退格键,因为它将在屏幕上打印出一些乱码。

我正在尝试使用haskeline修复此问题,同时我注释掉了我的main方法的大部分内容,以便每次更改都需要较少的编辑(我在'main'中注释掉的每个命令都与我保留的单个命令,因此,如果我可以使用此简化版本,则整个操作应该都可以)。基本上,我需要能够使用haskeline从用户那里获得输入,但是这样做之后,我还需要在“ do”块中运行一些“副作用”命令。

我是Haskell的新手,我不完全了解什么是不允许的或为什么的。这是我程序的简化版本:

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()”。

我知道“循环”的类型必须是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 个答案:

答案 0 :(得分:4)

由于InputT IOMonadIO的实例,因此您可以使用

将任何IO操作提升为InputT IO操作来运行
liftIO :: IO a -> InputT IO a

实际上,这是在支持IO但不IO的moand中“运行IO”的标准方法。

答案 1 :(得分:3)

InputT是MonadTrans的实例,所以

Just chords -> lift $ do

编辑:

liftControl.Monad.Trans.Class中。 (提示:Jon Purdy