Реализация PrimMonad для стека CatchT (ST) нового типа-d - PullRequest
0 голосов
/ 01 декабря 2018

Я пытаюсь заставить 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 для этого стека?

Обновление :для протокола, вот ответ, основанный на идее @ 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

1 Ответ

0 голосов
/ 01 декабря 2018

Вам нужно будет выставить параметр s:

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

forall s. ST s a Монада выглядит привлекательно, но она довольно бесполезна, поскольку (например) newSTRef не может позволитьссылка это создало побег.(Попробуйте заставить STRef s работать с вашей монадой, чтобы увидеть проблему)

Как только вы выставите s, экземпляр PrimMonad должен быть простым.

Также вы знаете о GeneralizedNewtypeDeriving, верно?Вам не нужно делать всю эту работу, чтобы создать оболочку нового типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...