问题描述
鉴于以下概念代码的证明,我希望能够以某种方式执行我的 foo
函数,并能够输出字符串 Paul !
以及在不使用 unsafePerformIO
的情况下获取其返回值到 InputT
monad- >在 runExceptT
之后移除IO包装。
import Control.Monad除了
导入System.IO.Unsafe(unsafePerformIO)
导入System.Console.Haskeline
类型ErrorWithIO = ExceptT字符串IO
foo :: String - > ErrorWithIO字符串
foopaul=做liftIO $ putStrLnPaul!
返回OK!
foo _ = throwError错误!
runRepl :: IO()
runRepl = runInputT defaultSettings $ loop
loop :: InputT IO()
loop = do
line< - getInputLine>
的情况行Nothing - > return()
只需输入 - >返回$ putStrLnasd
case unsafePerformIO $ runExceptT $ foo输入
Left err - > outputStrLn err>>循环
右分辨率 - >做
x< - outputStrLn。 show $ res
loop
$ b main :: IO()
main = runRepl>> putStrLn再见!
我是否在这里错过了一些明显的东西?
MonadIO
,所以您可以使用<$ c $ p $ lt; code> liftIO :: IO a - >这个类型的$ c> liftIO : InputT IO a
所以,
<$ p $
x< - liftIO $ runExceptT $ foo input
case x of
Left err - > ...
正确的资源 - > ...
或者,使用 Control.Monad.Trans.lift
代替。
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?
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.
这篇关于在InputT monad中执行Haskeline中的简单IO,而不必求助于unsafePerformIO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!