我正试图让renderText从xml-conduit那里得到ST monad的帮助。不幸的是,与renderBytes不同,它要求monad同时是PrimMonad和MonadThrow。IO满足这一点,但ST不满足。
renderText :: (PrimMonad m, MonadThrow m) => RenderSettings -> ConduitT Event Text m ()通过定义CatchT (ST s) a实例,我设法让它与PrimMonad堆栈一起工作:
instance PrimMonad m => PrimMonad (CatchT m) where type PrimState (CatchT m) = PrimState m primitive = lift . primitive
这是不健康的孤儿的例子。我试着把它包装成newtype,但被困在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
[???]我如何为这个堆栈定义PrimMonad?
Update:为了记录在案,下面是基于@luqui的想法的答案。
newtype Render s a = Render { runRender :: MaybeT (ST s) a }
deriving instance Functor (Render s)
deriving instance Applicative (Render s)
deriving instance Monad (Render s)
instance MonadThrow (Render s) where
throwM _ = Render $ MaybeT $ pure Nothing
instance PrimMonad (Render s) where
type PrimState (Render s) = s
primitive f = Render $ lift $ primitive f发布于 2018-11-30 23:39:31
您需要公开s参数:
newtype Render s a = Render { runRender :: MaybeT (ST s) a }forall s. ST s a monad看起来很吸引人,但是它非常无用,因为(例如) newSTRef不能让它创建的ref转义。(尝试让STRef与您的单曲一起工作,以了解问题所在)
一旦公开了s,PrimMonad实例就应该是简单明了的。
你也知道GeneralizedNewtypeDeriving的事,对吧?您不需要做所有这些工作来制作一个新类型的包装器。
https://stackoverflow.com/questions/53565931
复制相似问题