Haskell: 如何在同一个程序中使用haskline和写入文件
Haskell: how to use haskeline and write to a file in the same program
我在 Haskell 中编写了一个程序,它在当前目录中将吉他谱构建为 txt 文件。它从用户那里获取一串和弦,然后构建正确的输出并将其逐行写入文件。
我在使用 getLine 时无法在输入中使用退格键,因为它会在屏幕上打印出一堆乱码。
我正在尝试使用 haskeline 来解决这个问题,同时我注释掉了我的大部分主要方法,这样每次更改都需要更少的编辑(我在 'main' 中注释掉的每个命令都是与我保留的单个命令的类型相同,所以如果我能让这个简化版本工作,整个事情应该工作)。基本上,我需要能够使用 haskeline 从用户那里获取输入,但是之后我还需要在我的 "do" 块中 运行 一些 "side effects" 命令。
我是 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 ()
我直接从 Haskline 教程中获得了所有这些语法。我尝试了 运行ning 它但没有先做任何更改并且它起作用了,所以我知道这一切都是正确的 - 除了 - 我编辑的最后 3 行,我有 "do" 块并且正在尝试在 "return()".
之前调用 "writeFile"
我知道 "loop" 的类型必须是 InputT IO () 才能使用 getInputLine(getLine 的 haskeline 版本),但我不知道如何完成 "side effects"就像同时写入一个文件。
当我尝试在 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.
InputT 是 MonadTrans 的一个实例,所以
Just chords -> lift $ do
编辑:
lift
is in Control.Monad.Trans.Class. (Hat tip: Jon Purdy)
由于 InputT IO
是 MonadIO
的一个实例,您可以 运行 通过使用
将其提升为 InputT IO
操作来 运行 任何 IO 操作
liftIO :: IO a -> InputT IO a
事实上,这是 "run IO" 在支持 IO 但不 IO
的 moands 中的标准方法。
我在 Haskell 中编写了一个程序,它在当前目录中将吉他谱构建为 txt 文件。它从用户那里获取一串和弦,然后构建正确的输出并将其逐行写入文件。
我在使用 getLine 时无法在输入中使用退格键,因为它会在屏幕上打印出一堆乱码。
我正在尝试使用 haskeline 来解决这个问题,同时我注释掉了我的大部分主要方法,这样每次更改都需要更少的编辑(我在 'main' 中注释掉的每个命令都是与我保留的单个命令的类型相同,所以如果我能让这个简化版本工作,整个事情应该工作)。基本上,我需要能够使用 haskeline 从用户那里获取输入,但是之后我还需要在我的 "do" 块中 运行 一些 "side effects" 命令。
我是 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 ()
我直接从 Haskline 教程中获得了所有这些语法。我尝试了 运行ning 它但没有先做任何更改并且它起作用了,所以我知道这一切都是正确的 - 除了 - 我编辑的最后 3 行,我有 "do" 块并且正在尝试在 "return()".
之前调用 "writeFile"我知道 "loop" 的类型必须是 InputT IO () 才能使用 getInputLine(getLine 的 haskeline 版本),但我不知道如何完成 "side effects"就像同时写入一个文件。
当我尝试在 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.
InputT 是 MonadTrans 的一个实例,所以
Just chords -> lift $ do
编辑:
lift
is in Control.Monad.Trans.Class. (Hat tip: Jon Purdy)
由于 InputT IO
是 MonadIO
的一个实例,您可以 运行 通过使用
InputT IO
操作来 运行 任何 IO 操作
liftIO :: IO a -> InputT IO a
事实上,这是 "run IO" 在支持 IO 但不 IO
的 moands 中的标准方法。