[GHC] #8095: TypeFamilies painfully slow

GHC ghc-devs at haskell.org
Thu Oct 8 13:34:23 UTC 2015


#8095: TypeFamilies painfully slow
-------------------------------------+-------------------------------------
        Reporter:  MikeIzbicki       |                Owner:  bgamari
            Type:  bug               |               Status:  new
        Priority:  high              |            Milestone:  8.0.1
       Component:  Compiler (Type    |              Version:  7.6.3
  checker)                           |
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  Compile-time      |  Unknown/Multiple
  performance bug                    |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  5321              |  Differential Rev(s):
-------------------------------------+-------------------------------------

Comment (by simonpj):

 Good idea.  And here's an easier way to implement it: replace every (non-
 trivial) coercion in the program (specifically in cases) with `UnivCo`!

 That deals with the "sometimes we'll need to type of the result in the
 cast" question.

 But we need to take care.  If we start with
 {{{
 data T a where
   T1 :: Bool -> T Bool
   T2 :: T a

 f :: T a -> a -> Bool
 f = /\a (x:T a) (y:a).
     case x of
           T1 (c : a~Bool) (z : Bool) -> not (y |> c)
           T2 -> True
 }}}
 If we discard the cast, or turn it into UnivCo we might then wrongly float
 the not-expression, thus
 {{{
 f = /\a (x:T a) (y:a).
     let w :: Bool = not (y |> UnivCo a Bool)
     case x of
           T1 (c : a~Bool) (z : Bool) -> w
           T2 -> True
 }}}
 This woudl not have happened before, because the 'c' would prevent the
 not-expression being floated.  But if we dump the 'c' it could (utterly
 bogusly, and risking seg-faults) be floated.

 So if we are going to radically abbreviate to `UnivCo` or something like
 it, we should include the free variables of the coercion we have
 discarded, something like `UnivCo t1 tc [v1,...,vn]`.  So we'd get:
 {{{
 f :: T a -> a -> Bool
 f = /\a (x:T a) (y:a).
     case x of
           T1 (c : a~Bool) (z : Bool) -> not (y |> UnivCo a Bool [c])
           T2 -> True
 }}}
 But now what if `c` was itself bound to a big coercion?  Then the `UnivCo`
 would keep the big coercion alive.
 But it's ok: we should just substitute for `c` to get
 {{{
 UnivCo a Bool [big-coercion]
 }}}
 and now have a magic `UnivCo` optimisation to take the free vars of `big-
 coercion`:
 {{{
 UnivCo a Bool [v1,..,vn]
 }}}
 I think that would do it.

 We could do this in the desugarer; or even earlier in `setEvBind` in the
 type checker.  In the latter case we'd essentially kill off those big
 coercions at birth.

 Simon

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


More information about the ghc-tickets mailing list