Monad-coroutine 的 MonadError 实例 Coroutine for any suspension Functor
MonadError instance for monad-coroutine Coroutine for any suspension Functor
是否可以为 monad-coroutine
Coroutine
写一个 MonadError
实例并任意挂起 Functor
.
即
instance (MonadError e m, Functor s) => MonadError (Coroutine s m) where
throwError = lift . throwError
catchError c h = lift $ catchError (_ c) (_ . h)
洞里可以放什么?他们需要将 Coroutine s m r
转换为 m r
,但我不明白任意 s
.
怎么可能
是的,这是可能的。 Coroutine
和FreeT
本质上是一样的,后者有一个MonadError
实例。
请注意,您一开始就错了;你不能以 lift
开头。问题比你想象的更早出现。
catchError :: Coroutine f m a -> (e -> Coroutine f m a) -> Coroutine f m a
catchError c f = lift _
==>
_ :: m a
即使您不必处理捕获错误,也无法填补该漏洞!
lift
确实无法胜任一般提升 catch
类功能的任务。
此类型检查。不过我不确定这是否合法。
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-}
import Data.Bifunctor
import Control.Monad.Except
import Control.Monad.Coroutine
instance (MonadError e m, Functor s) => MonadError e (Coroutine s m) where
throwError = lift . throwError
Coroutine c `catchError` h = Coroutine $ fmap (first (fmap (`catchError` h))) c `catchError` (resume . h)
在英语中,它是这样工作的:首先,尝试 运行 c
的单步。可能的三种情况:
- 如果这会引发错误,那么我们会使用
h
和 return 处理错误。
- 如果成功并且 return 是最终值,那么我们 return 相同的最终值。
- 如果成功并且 return 暂停,那么我们还没有收到错误,但稍后可能会出现错误,因此我们
fmap (`catchError` h)
暂停函子 return , 递归以便我们以后有机会抓住它。
编辑:我在看到 dfeuer 的回答或知道 FreeT
的实例之前写了这篇文章,但那个实例与这个实例非常相似。这让我觉得这个是合法的。
是否可以为 monad-coroutine
Coroutine
写一个 MonadError
实例并任意挂起 Functor
.
即
instance (MonadError e m, Functor s) => MonadError (Coroutine s m) where
throwError = lift . throwError
catchError c h = lift $ catchError (_ c) (_ . h)
洞里可以放什么?他们需要将 Coroutine s m r
转换为 m r
,但我不明白任意 s
.
是的,这是可能的。 Coroutine
和FreeT
本质上是一样的,后者有一个MonadError
实例。
请注意,您一开始就错了;你不能以 lift
开头。问题比你想象的更早出现。
catchError :: Coroutine f m a -> (e -> Coroutine f m a) -> Coroutine f m a
catchError c f = lift _
==>
_ :: m a
即使您不必处理捕获错误,也无法填补该漏洞!
lift
确实无法胜任一般提升 catch
类功能的任务。
此类型检查。不过我不确定这是否合法。
{-# LANGUAGE FlexibleInstances, MultiParamTypeClasses, UndecidableInstances #-}
import Data.Bifunctor
import Control.Monad.Except
import Control.Monad.Coroutine
instance (MonadError e m, Functor s) => MonadError e (Coroutine s m) where
throwError = lift . throwError
Coroutine c `catchError` h = Coroutine $ fmap (first (fmap (`catchError` h))) c `catchError` (resume . h)
在英语中,它是这样工作的:首先,尝试 运行 c
的单步。可能的三种情况:
- 如果这会引发错误,那么我们会使用
h
和 return 处理错误。 - 如果成功并且 return 是最终值,那么我们 return 相同的最终值。
- 如果成功并且 return 暂停,那么我们还没有收到错误,但稍后可能会出现错误,因此我们
fmap (`catchError` h)
暂停函子 return , 递归以便我们以后有机会抓住它。
编辑:我在看到 dfeuer 的回答或知道 FreeT
的实例之前写了这篇文章,但那个实例与这个实例非常相似。这让我觉得这个是合法的。