[GHC] #12972: Missed specialisation opportunity with phantom type class parameter?

GHC ghc-devs at haskell.org
Wed Dec 14 21:35:19 UTC 2016


#12972: Missed specialisation opportunity with phantom type class parameter?
-------------------------------------+-------------------------------------
        Reporter:  mpickering        |                Owner:
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              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 danharaj):

 We discovered this while analyzing a moderately large production system
 based on `reflex` and `reflex-dom` compiled with ghcjs. Web applications
 that use this framework rely heavily on specialization in order to be
 performant when run in a browser. One feature of `reflex-dom` is a
 javascript FFI facility built to allow uniform interaction with either
 ghcjs's low-level JS FFI or a native JS engine (such as WebKit) when built
 with ghc. This type class is the user interface for this feature:


 {{{#!hs
 class (Monad m, MonadIO (JSM m), MonadFix (JSM m), MonadJS x (JSM m)) =>
 HasJS x m | m -> x where
   type JSM m :: * -> *
   liftJS :: JSM m a -> m a
 }}}


 The `x` parameter is important. There are situations where a program will
 manage multiple Javascript execution contexts. In general, references
 cannot be shared between execution contexts. So this is a slightly more
 elaborate version of the phantom type parameter used by the `ST` monad.
 The `x` parameter is used by the implementation of the FFI to tag various
 JS datastructures so that they cannot be intermixed: It guarantees this
 aspect of semantic correctness.


 Unfortunately, using this FFI via `HasJS` prevents automatic
 specialization because even though the dictionary for `HasJS` need not
 depend on `x` in an essential way, GHC seems unable to automatically
 create a specialized version of a polymorphic declaration that is
 constrained by `HasJS` and marked `INLINABLE`. I believe this is because,
 according to the documentation in the `Specialise` module, the invariant
 of the specialiser for generated specialisations is that "no specialised
 version is overloaded" and GHC cannot deduce that the overloading caused
 by `x` is benign.


 The workaround was to create an escape hatch that allowed the user to
 specify a concrete dummy type for `x` at the top-level, namely `()`. This
 allowed GHC to specialize all of their code which led to significant
 performance gains. This isn't the best situation: a user had to abandon
 type discipline ensuring semantic correctness in order to avoid
 unacceptable performance overhead.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12972#comment:1>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list