I have input data intended for my yet-to-be-written Haskell applications, which reside in a file. I don't update the file. I just need to read the file and feed it into my Haskell function which expects a list of strings. But reading the file of course yields IO
data objects. I have learned that using the <-
operation can "take out" somehow the strings packed in an IO
structure, so I tried this attempt:
run :: [String]
run = do
datadef_content <- readFile "play.txt" -- yields a String
let datadef = lines datadef_content -- should be a [String]
return datadef
I placed this into a file play.hs
and loaded it from ghci by
:l play
To my surprise, I got the error message for the readFile
line
Couldn't match type ‘IO’ with ‘[]’ Expected type: [String] Actual type: IO String
and for the return
the error message
Couldn't match type ‘[Char]’ with ‘Char’ Expected type: [String] Actual type: [[String]]
The first seems to indicate that I couldn't get rid of the IO
, and the last message seems to suggest, that lines
would return a list of list of strings, which also doesn't make sense to me.
How can I do this correctly?
You declare run
to be a [String]
value. But return
is not a keyword that provides the return value of a function; it is a function, with type Monad m => a -> m a
. return datadef
produces a value of type IO [String]
, which becomes the return value of the function.
The solution is to provide the correct return type for run
:
run :: IO [String]
run = do
...
run
can also be defined more succinctly as
run = fmap lines (readFile "play.txt")
Though the do
syntax suggests is, there is no way to pull a value out of an IO
action; all you can do is "push" the call to lines
into the action.