Реализация PrimMonad для стека CatchT (ST) нового типа-d
Я пытаюсь получить renderText
от xml-conduit
работать с ST
монада. К сожалению, в отличие от renderBytes
Монада должна быть 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
для этого стека?
1 ответ
Вам нужно будет выставить s
параметр:
newtype Render s a = Render { runRender :: MaybeT (ST s) a }
forall s. ST s a
Монада выглядит привлекательно, но это довольно бесполезно, так как (например) newSTRef
не могу позволить рефери, которую он создал, сбежать. (Попробуйте сделать STRef
s работать с вашей монадой, чтобы увидеть проблему)
Как только вы выставляете s
PrimMonad
экземпляр должен быть простым.
Также вы знаете о GeneralizedNewtypeDeriving
, право? Вам не нужно делать всю эту работу, чтобы сделать упаковщик нового типа.