I have the code
main :: IO()
main = runInputT defaultSettings loop
where
--loop :: InputT IO ()
loop = do
minput <- getInputLine "$ "
case minput of
Nothing -> return ()
Just input -> process $ words input
loop
Where process has the type definition
process :: [String] -> IO ()
However I get the error:
• Couldn't match type ‘IO’ with ‘InputT m’
Expected type: InputT m ()
Actual type: IO ()
• In the expression: process $ words input
In a case alternative: Just input -> process $ words input
In a stmt of a 'do' block:
case minput of {
Nothing -> return ()
Just input -> process $ words input }
I was wondering if anybody could explain what I'm doing wrong. I just want to raw input from getInputLine to do other things with.
Thanks
All statements in a do
block must have the same type (well, must have the same monad in their type). In your case, this is InputT IO something
(with the monad being InputT IO
).
getInputLine "$ "
has type InputT IO (Maybe String)
, so that part is OK.
Then you have a case
expression, which means all branches need to have the same type. The first branch is just return ()
, which gets the type InputT IO ()
. All good so far.
The second branch is process $ words input
. But this has type IO ()
, not InputT IO ()
, which is what the compiler expects at this point.
To fix this: Fortunately there's an easy way to convert ("lift") a value of type IO x
to InputT IO x
, which is the liftIO
function:
Just input -> liftIO (process $ words input)
That is, liftIO :: IO a -> InputT IO a
(actually it's more general than that: liftIO :: (MonadIO m) => IO a -> m a
but that doesn't matter here).