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 isInputT IO something
(with the monad beingInputT IO
).getInputLine "$ "
has typeInputT 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 justreturn ()
, which gets the typeInputT IO ()
. All good so far.The second branch is
process $ words input
. But this has typeIO ()
, notInputT 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
toInputT IO x
, which is theliftIO
function: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).