[GHC] #13158: Pattern synonyms should use type annotation information when typechecking

GHC ghc-devs at haskell.org
Thu Feb 9 11:34:36 UTC 2017


#13158: Pattern synonyms should use type annotation information when typechecking
-------------------------------------+-------------------------------------
        Reporter:  lexi.lambda       |                Owner:
            Type:  feature request   |               Status:  closed
        Priority:  normal            |            Milestone:
       Component:  Compiler (Type    |              Version:  8.0.1
  checker)                           |             Keywords:
      Resolution:  invalid           |  PatternSynonyms
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  GHC rejects       |  Unknown/Multiple
  valid program                      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #13159, #11350    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------
Changes (by simonpj):

 * status:  new => closed
 * resolution:   => invalid


Comment:

 This is a tricky one, but I think it is behaving correctly.

 Imagine desugaring it `evilId` like this
 {{{
 -- The original
 -- evilId (EqT (n :: Int)) = n + 1

 -- Desugars to
 evilId :: Typeable a => a -> a
 evilId x = case viewEqT x of
               Just (Refl, (n :: Int)) -> n + 1
               Nothing                 -> error "urk"
 }}}
 (The `error "urk"` is just a stub; in reality we arrange to fall through
 to the next equation, but we can ignore that here.)

 This fails with
 {{{
 T13158.hs:31:27: error:
     • Could not deduce: a ~ Int
       from the context: b0 ~ a
         bound by a pattern with constructor:
                    Refl :: forall k (a :: k). a :~: a,
                  in a case alternative
         at T13158.hs:31:20-23
 }}}
 It's not a great error message, but the payload is this

 * When calling `viewEqT` we must choose what types to instantiate it at;
 say `b := beta` and `a := alpha`.
 * Now the `Refl` brings into scope `alpha ~ beta`.
 * Now, inside that `Refl` match, the type signature `(n :: Int)` tells us
 that we need `beta ~ Int`.

 But `beta` is untouchable here (because of the equality) so we can't unify
 it.

 That is why you needed the type application in your other version `viewEqT
 @Int -> Just (Refl, n)`

 As #13159 points out, if we had type applications in patterns we could
 write
 {{{
 evilId (EqT @Int n) = ...
 }}}
 The ticket for that is #11350. Meanwhile I'll close this one as invalid.

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


More information about the ghc-tickets mailing list