
#12418: Make `MonadCont (ContT r m)` polykinded (r::k), (m::k -> Type) -------------------------------------+------------------------------------- Reporter: Iceland_jack | Owner: Type: feature request | Status: new Priority: normal | Milestone: Component: Core Libraries | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by ekmett): {{{#!hs instance MonadState s m => MonadState s (ContT @Type r m) }}} suffers the same sort of problem as the MonadCont instance, if you define it pointwise at @Type. If m and r are left underspecified kind wise and you go to invoke a `MonadState s ` operation, it has no reason to pick that instance, unless it can figure out `k = Type`, hence `m :: Type -> Type`, it won't discharge the head and go looking for `MonadState s m` from the body and use this instance. It'll just whine about a missing instance at an unknown kind. So if `m` is polykinded like `Proxy`, which has kind k -> *, but at * -> * is a perfectly legitimate monad (it is the unique-up-to-isomorphism terminal monad), then this no longer monomorphizes m to kind * -> * to go look for this possible instance. The compiler doesn't know if you doesn't know someone won't make up some completely different instance like: {{{#!hs instance MonadState () (ContT @Whatever r m) where get = return () put () = return () }}} pointwise at another kind. This 'can't do the same sort of lifting as the typical MonadState, so it really doesn't have any place being defined on this data type and any such instance will necessarily be an orphan. As you note Functor, Applicative, Monad all work fine, because really if you look at ContT the fact that m and r exist as separate entities doesn't matter to those instances at all, those are just the basic `Cont r'` instances instantiated at `r' = m r`. They never use 'm' to do any work, and just teeat `m r` as an opaque blob. Once you start lifting monad transformer instances for things like MonadState, MonadWriter, etc. over `ContT r` then we need to know `m :: Type -> Type`, because we finally start interacting with the extra structure we've given our CPS'd result type. You get a slightly more general callCC at the expense of screwing up inference for every monad transformer instance, that can only be taken advantage of to make instances that act at different kinds inconsistently with the instances that are already in place. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12418#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler