[GHC] #12430: TypeFamilyDependencies accepts invalid injectivity annotation

GHC ghc-devs at haskell.org
Sun Jul 24 16:16:49 UTC 2016


#12430: TypeFamilyDependencies accepts invalid injectivity annotation
-------------------------------------+-------------------------------------
           Reporter:  vagarenko      |             Owner:
               Type:  bug            |            Status:  new
           Priority:  high           |         Milestone:
          Component:  Compiler       |           Version:  8.0.1
  (Type checker)                     |
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  GHC accepts
  Unknown/Multiple                   |  invalid program
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 Consider this code (depends on singletons-2.2):

 {{{#!hs
 {-# LANGUAGE TypeFamilies, DataKinds, PolyKinds, TypeOperators,
 KindSignatures, TypeInType, TypeFamilyDependencies, UndecidableInstances
 #-}

 module Bug where

 import Data.Kind (Type)
 import Data.Singletons.Prelude (Map, SndSym0)
 import GHC.TypeLits (Nat)

 data Payload = A | B

 newtype NewType a = NewType Int

 type NatList = [(Nat, Payload)]

 type StripNatList (natList :: NatList) = Map SndSym0 natList

 type family Family (natList :: NatList) = (r :: Type) | r -> natList where
     Family '[] = ()
     Family xs  = NewType (StripNatList xs)
 }}}

 Why GHC is okay with injectivity annotation for `Family`: `r -> natList`?

 These two types:

 {{{#!hs
 type Foo = Family '[ '(0, 'A), '(1, 'B)]
 type Bar = Family '[ '(0, 'A), '(0, 'B)]
 }}}
 are obviously map to the same type:

 {{{#!hs
 *Bug Data.Singletons.Prelude> :kind! Foo
 Foo :: *
 = NewType ('A :$$$ '['B])
 *Bug Data.Singletons.Prelude> :kind! Bar
 Bar :: *
 = NewType ('A :$$$ '['B])
 }}}
 ----
 If inline `StripNatList` inside `Family` definition:
 {{{#!hs
 type family Family (natList :: NatList) = (r :: Type) | r -> natList where
     Family '[] = ()
     Family xs  = NewType (Map SndSym0 xs)
 }}}
 or change `StripNatList` definition to type family:
 {{{#!hs
 type family StripNatList (natList :: NatList) where
     StripNatList '[] = '[]
     StripNatList ('(n, x) ': xs) = x ': StripNatList xs
 }}}
 compilation expectedly fails with `Type family equation violates
 injectivity annotation.`
 ----
 Moreover, if I remove `NewType` from `Family` and change result kind:
 {{{#!hs
 type family Family (natList :: NatList) = (r :: [Payload]) | r -> natList
 where
     Family xs = StripNatList xs
 }}}
 it fails with correct error regardless of `StripNatList` definition.

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


More information about the ghc-tickets mailing list