[GHC] #12362: don't complain about type variable ambiguity when the expression is parametrically polymorphic

GHC ghc-devs at haskell.org
Sun Jul 3 19:05:19 UTC 2016


#12362: don't complain about type variable ambiguity when the expression is
parametrically polymorphic
-------------------------------------+-------------------------------------
           Reporter:  rwbarton       |             Owner:
               Type:  feature        |            Status:  new
  request                            |
           Priority:  low            |         Milestone:
          Component:  Compiler       |           Version:  8.1
  (Type checker)                     |
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 I'm not sure this is really a good idea, but it did come up in practice.
 Consider the following rather contrived program:
 {{{#!hs
 {-# LANGUAGE TypeFamilies, RankNTypes, ScopedTypeVariables,
              AllowAmbiguousTypes, TypeApplications #-}

 module E where

 type family T a
 type instance T Int = Char
 type instance T String = Char
 type instance T Bool = ()

 newtype FT a = FT [T a]

 m :: forall a. (forall x. T x -> Int) -> FT a -> [Int]
 m f (FT xs) = map f xs
 }}}
 GHC rejects it with the error:
 {{{
 E.hs:14:21: error:
     • Couldn't match type ‘T a’ with ‘T x0’
       Expected type: [T x0]
         Actual type: [T a]
       NB: ‘T’ is a type function, and may not be injective
       The type variable ‘x0’ is ambiguous
     • In the second argument of ‘map’, namely ‘xs’
       In the expression: map f xs
       In an equation for ‘m’: m f (FT xs) = map f xs
     • Relevant bindings include
         xs :: [T a] (bound at E.hs:14:9)
         m :: (forall x. T x -> Int) -> FT a -> [Int] (bound at E.hs:14:1)
 }}}
 The problem seems to be that GHC doesn't know at what type to instantiate
 `f`, because it can't conclude from the argument of `f` being `T a` that
 the type parameter of `f` needs to be `x`. In fact, `T` here really is not
 injective, so if `a` is `Int`, `x` could just as well be `String`.

 However, in this case the ambiguity doesn't actually matter. If `f @Int`
 and `f @String` have the same type because `T Int ~ T String`, then they
 are actually the same value too by parametricity, because there is no
 class constraint on `x`. Since GHC prints a message saying that `T` is not
 known to be injective, it sounds like it knows about the possible solution
 `x0 = a`. So it could just pick it, and accept the original program.

 With TypeApplications I can just specify the intended value of `x` by
 writing
 {{{
 m f (FT xs) = map (f @a) xs
 }}}
 which is a reasonable workaround in my real use case also. Interestingly I
 can't seem to achieve the same thing without TypeApplications without
 adding a proxy argument to `f`, which I don't much want to do.

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


More information about the ghc-tickets mailing list