1

I'm getting a result from getInputline, whose type is:

(MonadException m) => IO String -> InputT m (Maybe String)

I'd like to get just the Maybe String part. I'm well aware that in general there is no way to strip a monad, as explained in this answer (and other answers in the same question). However, since I'm doing it inside an InputT, I guess it's possible, as proposed here. However, I can't just use liftIO, as the answer suggests, since the IO is inside a StateT.

loop :: Counter -> InputT (StateT [String] IO) ()    
loop c = do
        minput <- getLineIO $ in_ps1 $ c
        case minput of
          Nothing -> outputStrLn "Goodbye."
          Just input -> (process' c input) >> loop c      

getLineIO :: (MonadException m) => IO String -> InputT m (Maybe String)
getLineIO ios = do
    s <- liftIO ios
    getInputLine s

process' :: Counter -> String -> InputT (StateT [String] IO) ()
[...]

The error I'm getting:

Main.hs:81:15:
    No instance for (MonadException (StateT [String] IO))
      arising from a use of ‘getLineIO’
    In the expression: getLineIO
    In a stmt of a 'do' block: minput <- getLineIO $ in_ps1 $ c
    In the expression:
      do { minput <- getLineIO $ in_ps1 $ c;
           case minput of {
             Nothing -> outputStrLn "Goodbye."
             Just input -> (process' c input) >> loop c } }

If I remove getLineIO and use getInputLine directly, as per @chepner's advice:

loop :: Counter -> InputT (StateT [String] IO) ()
loop c = do
    minput <- (in_ps1 c) >>= getInputLine
    case minput of
      Nothing -> outputStrLn "Goodbye."
      Just input -> (process' c input) >> loop c

I'm getting an error:

Main.hs:81:16:
    Couldn't match type ‘IO’ with ‘InputT (StateT [String] IO)’
    Expected type: InputT (StateT [String] IO) String
      Actual type: IO String
    In the first argument of ‘(>>=)’, namely ‘(in_ps1 c)’
    In a stmt of a 'do' block: minput <- (in_ps1 c) >>= getInputLine

Full code can be found here, and explanations about what I'm trying to do can be found here.

Community
  • 1
  • 1
dimid
  • 7,285
  • 1
  • 46
  • 85
  • Yes, `liftIO` is `liftIO :: MonadIO m => IO a -> m a`, and `getLineIO` is a wrapper. The only difference that it takes an argument of `IO String` instead of `getInputLine`'s regular `String`. How would you suggest to unwrap it? – dimid Jun 28 '16 at 13:02
  • If `getInputLine` just takes a regular string, then `getLineIO ios = ios >>= getInputLine`. You don't need `lift`. – chepner Jun 28 '16 at 13:35
  • Thanks, but I'm not sure I'm following you. Please see the updated question, is that what you had in mind? – dimid Jun 28 '16 at 13:51

0 Answers0