我正尝试从renderText
的{{1}}单子中获得xml-conduit
。不幸的是,与ST
不同,它要求monad同时为renderBytes
和PrimMonad
。 MonadThrow
满足此要求,但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
答案 0 :(得分:2)
您将需要公开s
参数:
newtype Render s a = Render { runRender :: MaybeT (ST s) a }
一个forall s. ST s a
单子看起来很吸引人,但是却毫无用处,因为newSTRef
不能让它创建的引用逃脱。 (尝试让STRef
与您的monad一起工作以查看问题)
一旦公开s
,PrimMonad
实例就应该很简单。
您还了解GeneralizedNewtypeDeriving
,对吗?您不必做所有这些工作就可以制作新类型的包装器。