I wrote a program in Haskell that builds a guitar tab as a txt file in the current directory. It gets a String of chords from the user, and then builds the proper output and writes it line by line to a file.
I wasn't able to use the backspace key on my input when I was using getLine, because it would print a bunch of gibberish to the screen.
I'm trying to use haskeline to fix this, and I commented out the bulk of my main method in the meantime so that each change requires less editing (every command I commented out in 'main' is of the same type as the single command I kept, so if I can get this simplified version to work, the whole thing should work). Basically, I need to be able to get the input from the user using haskeline, but then I also need to run some "side effects" commands in my "do" block after I do that.
I'm new to Haskell and I don't fully understand what is and is not allowed or why. Here's the simplified version of my program:
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 ()
I got all of this syntax straight from a Haskeline tutorial. I tried running it without making any changes first and it worked, so I know that it's all correct -except- for the last 3 lines that I edited, where I have the "do" block and am trying to call "writeFile" before "return()".
I know that the type of "loop" has to be InputT IO () in order to use getInputLine (the haskeline version of getLine), but I don't know how to accomplish "side effects" like writing to a file at the same time.
When I try to load my project in ghci, I get the following error:
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.
Since
InputT IOis an instance ofMonadIO, you can run any IO action by lifting it to aInputT IOaction, usingIndeed, this is the standard way to "run IO" in moands that support IO but aren't
IO.