[GHC] #12418: Make `MonadCont (ContT r m)` polykinded (r::k), (m::k -> Type)

GHC ghc-devs at haskell.org
Sun Jul 24 00:11:41 UTC 2016


#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


More information about the ghc-tickets mailing list