haskell - Accessing an instance method embedded in the monad stack -
haskell - Accessing an instance method embedded in the monad stack -
i have defined newtype wrapper on monad stack struggling work out how implement "already" implemented typeclass method. feels should easy utilise gmask method ghc in exceptionmonad instance enginem can't head around necessary boilerplate , lifting work correctly. pointers?
newtype enginem = enginem { _runenginem :: rwst engineenv enginelog enginestate ghc } instance exceptionmonad ghc ... -- implemented instance exceptionmonad enginem gmask :: ((m -> m a) -> m b) -> m b gmask f = ??
we can create easier providing orphan instances rwst ghc typeclasses monadio , exceptionmonad. fits general strategy building interpreters transformers - write classes each property, implement how each transformer preserves property, , derive classes on final transformer stack
{-# language generalizednewtypederiving #-} i'm going prefix of imports ghc api ghc can maintain them straight.
import control.applicative import data.monoid import control.monad.trans.class import control.monad.trans.rws.strict import qualified exception ghc import qualified ghcmonad ghc import qualified monadutils ghc we'll maintain definition of enginem, deriving type classes interested in.
newtype enginem = enginem { _runenginem :: rwst engineenv enginelog enginestate ghc.ghc } deriving (ghc.exceptionmonad, ghc.monadio, monad, applicative, functor) making ghc.monadio instance rwst straightforward in terms of lift control.monad.trans.class. need because ghc.monadio superclass of ghc.exceptionmonad.
instance (monoid w, ghc.monadio m) => ghc.monadio (rwst r w s m) liftio = lift . ghc.liftio a ghc.exceptionmonad instance trickier. may have noticed rwst comes liftcatch function lifting things ghc.gcatch. bulk of problem providing gmask definition.
instance (monoid w, ghc.exceptionmonad m) => ghc.exceptionmonad (rwst r w s m) gcatch = liftcatch ghc.gcatch gmask f = rwst $ \r s -> ghc.gmask $ \restore -> runrwst (f (maprwst restore)) r s it's bit hard explain, first i'll write out of types involved
liftmask :: (((m (a, s, w) -> m (a, s, w)) -> m (b, s, w)) -> m (b, s, w)) -> ((rwst r w s m -> rwst r w s m a) -> rwst r w s m b) -> rwst r w s m b liftmask mask f = rwst $ \r s -> mask $ \restore -> runrwst (f (maprwst restore)) r s the thought here that, given way mask async errors in arbitrary computations m -> m a, have value m b. whole type of such value hence (m -> m a) -> m b. gmask needs provide way mask async errors in arbitrary computations, , in doing can convert value depends on ability m b. why gmask has convoluted type ((m -> m a) -> m b) -> m b.
since result of computation must m b, or in our case rwst r w s m b, can start returning constructor one. rwst :: r -> s -> m (b, s, w) -> rwst r w s m b. if start writing function definition here, gives r , s later when need them. next thing encounter m m (b, s, w), hand off work underling mask. need provide function that, given way mask async errors, returns m (b, s, w). we'll phone call way mask async errors restore. way have create b need stuck within f, expects way mask async errors type rwst r w s m -> rwst r w s m a types a. maprwst converts function m (a, s, w) -> m (a, s, w) function rwst r w s m -> rwst r w s m a, , gmask promised restore way mask async errors m a1 -> m a1 types a1, maprwst restore way mask async errors need pass f. faced tiny problem f returned rwst r w s m b need m (b, s, w). runrwst m (b, s, w) rwst r w s m b if have r , s. fortunately have r , s sitting around outermost function, , we're done.
haskell
Comments
Post a Comment