Perform simple IO in Haskeline, inside InputT monad, without having to resort to unsafePerformIO

為{幸葍}努か 提交于 2019-12-04 03:13:21

问题


Given the proof of concept code below I'd like to be able to somehow perform my foo function with the ability to output the string Paul! and the possibility of getting its return value inside the InputT monad-transformer without using unsafePerformIO to remove the IO wrapper after runExceptT.

import Control.Monad.Except

import System.IO.Unsafe (unsafePerformIO)
import System.Console.Haskeline


type ErrorWithIO = ExceptT String IO


foo :: String -> ErrorWithIO String
foo "paul" = do liftIO $ putStrLn "Paul!"
                return "OK!"
foo _ = throwError "ERROR!"


runRepl :: IO ()
runRepl = runInputT defaultSettings $ loop


loop :: InputT IO ()
loop = do
    line <- getInputLine "> "
    case line of
        Nothing -> return ()
        Just input -> do return $ putStrLn "asd"
                         case unsafePerformIO $ runExceptT $ foo input of
                             Left err -> outputStrLn err >> loop
                             Right res -> do
                                 x <- outputStrLn . show $ res
                                 loop




main :: IO ()
main = runRepl >> putStrLn "Goodbye!"

Am I missing something obvious here?


回答1:


Since InputT IO is a MonadIO, you can use liftIO with this type:

liftIO :: IO a -> InputT IO a

So,

do ...
   x <- liftIO $ runExceptT $ foo input
   case x of
     Left err  -> ...
     Right res -> ...

Alternatively, use Control.Monad.Trans.lift instead.



来源:https://stackoverflow.com/questions/28053526/perform-simple-io-in-haskeline-inside-inputt-monad-without-having-to-resort-to

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!