【发布时间】:2011-12-22 21:41:36
【问题描述】:
我有以下 monad 转换器来处理 Haskell 中的错误。
instance (Monad m, Error e) => Monad (EitherT e m) where
return = EitherT . return . return
m >>= k = EitherT $ do
a <- runEitherT m
case a of
Left l -> return (Left l)
Right r -> runEitherT (k r)
fail = EitherT . return . Left . strMsg
它工作得很好,因为我可以使用自定义类来实例化Error,并且有一种非常灵活的方式来处理错误。
fail 有点傻,因为它是String -> EitherT e m 类型,而String 限制可能是一种令人讨厌的创建错误的方式。我最终得到了很多:
instance Error BazError where
strMsg "foo" = FooError -- oh look we have no error context
strMsg "bar" = BarError -- isn't that nice
我想做的是创建一个新函数,比如fail,它的类型是a -> e,这样我就可以删除(Error e) 限制。 fail 在 monad 堆栈变大时特别方便,比如当我结束时
EitherT BazError (StateT [BazWarning] IO) Foo
有没有一种方法可以创建一个与fail 行为相同但类型限制较少的函数?还是fail 是用深层次的haskell 暗魔法实现的?
【问题讨论】:
-
你应该完全避免
fail,除非你想自定义失败的do-block模式匹配的行为。
标签: haskell monads monad-transformers