【发布时间】:2010-11-16 07:43:46
【问题描述】:
我无法理解 monad 和 monad 转换器。我有 以下人为示例(不可编译):
import Control.Monad
import Control.Monad.Error
import Control.Monad.Reader
data State = State Int Int Int
type Foo = ReaderT State IO
readEither :: String -> Either String Int
readEither s = let p = reads s
in case p of
[] -> throwError "Could not parse"
[(a, _)] -> return a
readEitherT :: IO (Either String Int)
readEitherT = let p s = reads s
in runErrorT $ do
l <- liftIO (getLine)
readEither l
foo :: Foo Int
foo = do
d <- liftIO $ readEitherT
case d of
Right dd -> return dd
Left em -> do
liftIO $ putStrLn em
return (-1)
bar :: Foo String
bar = do
liftIO $ getLine
defaultS = State 0 0 0
如果我将 readEither 的功能复制到 readEitherT,它可以工作,但我
有一种唠叨的感觉,我可以利用现有的力量
readEither 函数,但我不知道如何。如果我尝试抬起
readEither 在 readEitherT 函数中,它应该将其提升到 ErrorT String IO
(Either String Int) 。但我应该以某种方式将其发送给ErrorT
String IO Int。
如果我走错了方向,那么正确的方法是什么
处理需要 IO(或其他 monads)并且将从中调用的错误
一元上下文(参见示例中的foo 函数)
编辑: 显然我不清楚我想做什么。也许以下函数描述了我想知道的内容和原因
maybePulseQuit :: Handle -> IO (Either String ())
maybePulseQuit h = runErrorT $ do
f <- liftIO $ (communicate h "finished" :: IO (Either String Bool))
(ErrorT . pure) f >>= \b → liftIO $ when b $ liftIO pulseQuit
这可行,但由于绑定仍然很难看。这比以前的有大小写检查的版本要清楚得多。这是推荐的方法吗?
【问题讨论】:
标签: haskell error-handling monads monad-transformers