在 InputT monad 内部的 Haskeline 中执行简单的 IO,而不必求助于 unsafePerformI



鉴于下面的概念验证代码,我希望能够以某种方式执行我的foo函数,能够输出字符串Paul!,并有可能在InputT monad-transformer内获取其返回值,而无需在runExceptT后使用unsafePerformIO删除IO包装器。

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!"

我在这里错过了一些明显的东西吗?

由于InputT IO是一个MonadIO,你可以用liftIO来做这个类型:

liftIO :: IO a -> InputT IO a

所以

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

或者,改用Control.Monad.Trans.lift

相关内容

  • 没有找到相关文章

最新更新