[GHC] #14552: GHC panic on pattern synonym

GHC ghc-devs at haskell.org
Thu Dec 14 20:03:22 UTC 2017


#14552: GHC panic on pattern synonym
-------------------------------------+-------------------------------------
        Reporter:  Iceland_jack      |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:
       Component:  Compiler          |              Version:  8.3
      Resolution:                    |             Keywords:
                                     |  PatternSynonyms, TypeInType,
                                     |  ViewPatterns
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 goldfire):

 Simon asked me to take a look at this pattern synonym, as there are deeper
 issues here.

 Here is a much simpler scenario with similar issues:

 {{{#!hs
 data T where
   T :: (forall a. Int -> a -> a) -> T

 pattern PT x <- T (($ 3) -> x)
 }}}

 What type should `PT` have? Here are two possibilities: (renaming for
 clarity, but both have the same definition)

 {{{#!hs
 pattern PT1 :: forall a. (a -> a) -> T
 pattern PT2 :: (forall a. a -> a) -> T
 }}}

 These synonyms correspond to the following two matchers:

 {{{#!hs
 matcher1 :: forall r a. T -> ((a -> a) -> r) -> r
 matcher1 (T f) k = k (f 3)

 matcher2 :: forall r. T -> ((forall a. a -> a) -> r) -> r
 matcher2 (T f) k = k (f 3)
 }}}

 Both type-check. The second is more general than the first, even though
 the first is what GHC infers for the definition if given the chance. So,
 which matcher should we generate for `PT`?

 However, I've just played a trick on you. Notice that I inlined the use of
 `($)` in my matchers. Interestingly, `matcher2` does not type check
 without this inlining:

 {{{#!hs
 matcher2 (T (($ 3) -> x)) k = k x   -- does not type-check
 }}}

 This fails because it contains an unsaturated use of `($)`, and
 unsaturated uses of `($)` do not get the pseudo-impredicative magic that
 saturated uses of `($)` get. So, really, `matcher1` is the only
 possibility. (Indeed, GHC infers a pattern type of `forall a. (a -> a) ->
 T` for `PT`.)

 In the original program, the question above (where to generalize) isn't
 properly formed. That's because the equivalent of the `a` here (called
 `aa` in the example) has an existentially-bound kind, so it can't possibly
 scope over the whole matcher type. (In other words, it can't be like
 `matcher1`.) As I've already argued, it also can't be like `matcher2`
 (because `($)` isn't impredicative in this scenario). So, it must be like
 `matcher3`:

 {{{#!hs
 matcher3 :: forall r. T -> ((Any -> Any) -> r) -> r
 matcher3 (T (($ 3) -> x)) k = k x
 }}}

 This is a bit silly, but it's the best we can do if we can't generalize
 over `a`. In the original program, this is really

 {{{#!hs
 matcher :: Exp xs t -> (forall k (f :: k --> Type). Exp xs (f @@ Any) ->
 r) -> r
 matcher (TLam (Proxy :: Proxy this_f) (($ (Proxy @Any)) -> z)) k = k @_
 @this_f z
 }}}

 Probably not what the user wanted, but I don't see how we can do better
 without an impredicative unsaturated `($)`.

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


More information about the ghc-tickets mailing list