haskell - 在 Haskeline 中的 InputT monad 中执行简单 IO,而不必求助于 unsafePerformIO

标签 haskell monad-transformers haskeline

鉴于下面的概念验证代码,我希望能够以某种方式执行我的 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 代替。

关于haskell - 在 Haskeline 中的 InputT monad 中执行简单 IO,而不必求助于 unsafePerformIO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28053526/

相关文章:

haskell - 不安全 IO 或 : Haskeline and Directories

haskell - 重载列表扩展不起作用

Haskell ncurses

haskell - 返回由 Haskell 中的两次插入修改的图

haskell - IO monad 内部的惰性计算

haskell - 同一个单子(monad)变压器的不同排序有什么区别?

ado.net - F# 中的 Haskell HDBC 优雅?

haskell - mtl、transformers、monads-fd、monadLib 和选择悖论

haskell - 具有 Haskeline 自动完成功能的不明确类型变量