为 newtype-d CatchT (ST s) 栈实现 PrimMonad
Implementing PrimMonad for newtype-d CatchT (ST s) stack
我正在尝试使用 ST
monad 从 xml-conduit
中获取 renderText
。不幸的是,与 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
这是一个运行状况不佳的孤立实例。我试图将它包装成新类型,但卡在 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
?
更新:作为记录,这里是根据@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
您将需要公开 s
参数:
newtype Render s a = Render { runRender :: MaybeT (ST s) a }
A forall s. ST s a
monad 看起来很吸引人,但它非常无用,因为(例如)newSTRef
不能让它创建的引用逃逸。 (尝试让 STRef
s 与你的 monad 一起工作以查看问题)
公开 s
后,PrimMonad
实例应该很简单。
你也知道GeneralizedNewtypeDeriving
,对吧?你不必做所有这些工作来制作一个新的包装器。
我正在尝试使用 ST
monad 从 xml-conduit
中获取 renderText
。不幸的是,与 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
这是一个运行状况不佳的孤立实例。我试图将它包装成新类型,但卡在 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
?
更新:作为记录,这里是根据@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
您将需要公开 s
参数:
newtype Render s a = Render { runRender :: MaybeT (ST s) a }
A forall s. ST s a
monad 看起来很吸引人,但它非常无用,因为(例如)newSTRef
不能让它创建的引用逃逸。 (尝试让 STRef
s 与你的 monad 一起工作以查看问题)
公开 s
后,PrimMonad
实例应该很简单。
你也知道GeneralizedNewtypeDeriving
,对吧?你不必做所有这些工作来制作一个新的包装器。