为新型D CatchT(ST)堆栈实现PrimMonad

时间:2018-11-30 22:47:52

标签: haskell monad-transformers

我正尝试从renderText的{​​{1}}单子中获得xml-conduit。不幸的是,与ST不同,它要求monad同时为renderBytesPrimMonadMonadThrow满足此要求,但IO不满足。

ST

通过定义PrimMonad实例,我设法使其与renderText :: (PrimMonad m, MonadThrow m) => RenderSettings -> ConduitT Event Text m () 堆栈配合使用:

CatchT (ST s) a

这是不健康的孤立实例。我试图将其包装成新类型,但被卡在instance PrimMonad m => PrimMonad (CatchT m) where type PrimState (CatchT m) = PrimState m primitive = lift . primitive 上。

PrimMonad

如何为该堆栈定义newtype Render a = Render { runRender :: forall s. MaybeT (ST s) a } instance Functor Render where fmap f (Render m) = Render (fmap f m) instance Applicative Render where pure a = Render (pure a) (Render f) <*> (Render v) = Render (f <*> v) instance Monad Render where a >>= f = Render $ do v <- runRender a runRender (f v) instance MonadThrow Render where throwM _ = Render $ MaybeT $ pure Nothing instance PrimMonad Render where [???]

更新:为记录下来,这是基于@luqui想法的答案。

PrimMonad

1 个答案:

答案 0 :(得分:2)

您将需要公开s参数:

newtype Render s a = Render { runRender :: MaybeT (ST s) a }

一个forall s. ST s a单子看起来很吸引人,但是却毫无用处,因为newSTRef不能让它创建的引用逃脱。 (尝试让STRef与您的monad一起工作以查看问题)

一旦公开sPrimMonad实例就应该很简单。

您还了解GeneralizedNewtypeDeriving,对吗?您不必做所有这些工作就可以制作新类型的包装器。