[Haskell-cafe] Coercing newtype-wrapped monad transformers?
Viktor Dukhovni
ietf-dane at dukhovni.org
Sun May 10 19:20:56 UTC 2020
On Sun, May 10, 2020 at 11:28:43PM +0900, 宮里洸司 wrote:
> Hello, I think I can answer.
Many thanks, you answer was perfect.
> In the failing code, the type of "M.ask" have no constraint, so it gets the type
> "(Monad m0) => M.RWST r0 w0 s0 m0 r0", where "r0, w0, s0, m0" are some
> unconstrained types.
>
> To resolve "Coercible (M.RWST r0 w0 s0 m0 r0) (FooT r w s m r)", you can
>
> You want "m0" be equal to "m", but it can't be inferred.
>
> > ask :: Monad m => RWST r w s m r -- You mean FooT? [yes]
> > ask = coerce M.ask
>
> This error can be fixed by specifying concrete type you want.
>
> {-# LANGUAGE ScopedTypeVariables #-}
> ask :: forall m r w s. Monad m => FooT r w s m r
> ask = coerce (M.ask :: M.RWST r w s m r)
I ended going with the below, with my module exporting only a
higher-level interface that uses RWST internally, but exports
a more abstract monad, hiding the implementation details.
{-# LANGUAGE ScopedTypeVariables #-}
import qualified Control.Monad.Trans.RWS.CPS as RWS
import Data.Coerce (coerce)
newtype RWST r w s m a = RWST (RWS.RWST r w s m a)
deriving instance MonadTrans (RWST r w s)
deriving instance (Monad m) => Functor (RWST r w s m)
deriving instance (Monad m) => Applicative (RWST r w s m)
deriving instance (Monad m) => Monad (RWST r w s m)
type EvalM f r w s m a = (Monoid w, Monad m) => f r w s m a -> r -> s -> m (a, w)
evalRWST :: forall r w s m a. EvalM RWST r w s m a
evalRWST = coerce (RWS.evalRWST :: EvalM RWS.RWST r w s m a)
type AskM f r w s m = Monad m => f r w s m r
ask :: forall r w s m. AskM RWST r w s m
ask = coerce (RWS.ask :: AskM RWS.RWST r w s m)
type GetM f r w s m = Monad m => f r w s m s
get :: forall r w s m. GetM RWST r w s m
get = coerce (RWS.get :: GetM RWS.RWST r w s m)
type PutM f r w s m = (Monad m) => s -> f r w s m ()
put :: forall r w s m. PutM RWST r w s m
put = coerce (RWS.put :: PutM RWS.RWST r w s m)
type TellM f r w s m = (Monoid w, Monad m) => w -> f r w s m ()
tell :: forall r w s m. TellM RWST r w s m
tell = coerce (RWS.tell :: TellM RWS.RWST r w s m)
type GetsM f r w s m a = Monad m => (s -> a) -> f r w s m a
gets :: forall r w s m a. GetsM RWST r w s m a
gets = coerce (RWS.gets :: GetsM RWS.RWST r w s m a)
type LocalM f r w s m a = Monad m => (r -> r) -> f r w s m a -> f r w s m a
local :: forall r w s m a. LocalM RWST r w s m a
local = coerce (RWS.local :: LocalM RWS.RWST r w s m a)
type PassM f r w s m a w' = (Monoid w, Monoid w', Monad m) => f r w' s m (a, w' -> w) -> f r w s m a
pass :: forall r w s m a w'. PassM RWST r w s m a w'
pass = coerce (RWS.pass :: PassM RWS.RWST r w s m a w')
... etc. if/as more are needed later ...
--
Viktor.
More information about the Haskell-Cafe
mailing list