[GHC] #13538: Weird kind inference problems with closed type families

GHC ghc-devs at haskell.org
Thu Apr 6 08:32:35 UTC 2017


#13538: Weird kind inference problems with closed type families
-------------------------------------+-------------------------------------
           Reporter:  achirkin       |             Owner:  (none)
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  8.0.2
  (Type checker)                     |
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  Incorrect
  Unknown/Multiple                   |  error/warning at compile-time
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 Consider a problem of injective cons on a type-level list
 [https://ghc.haskell.org/trac/ghc/ticket/12114]. I made a small workaround
 by adding an intermediate data type `List1 k`. Here is my code:
 {{{#!hs
 {-# LANGUAGE UndecidableInstances #-}
 {-# LANGUAGE TypeFamilies, TypeFamilyDependencies #-}
 {-# LANGUAGE KindSignatures, DataKinds, PolyKinds #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE TypeApplications     #-}
 module TFTest where

 import GHC.TypeLits
 import Data.Proxy



 -- | Synonym for a type-level snoc (injective!)
 type (ns :: [k]) +: (n :: k) = GetList1 (SinkFirst (n ': ns))
 infixl 5 +:



 -- | A weird data type used to make `(+:)` operation injective.
 --   `List k [k]` must have at least two elements.
 data List1 k = L1Single k | L1Head k [k]

 -- | Sink first element of a list to the end of the list
 type family SinkFirst (xs :: [k]) = (ys :: List1 k) | ys -> xs where
   SinkFirst '[y]       = 'L1Single y
   -- SinkFirst (y ': x ': xs :: [Nat])
   --     = ('L1Head x (GetList1Nat (SinkFirst (y ': xs))) :: List1 Nat)
   SinkFirst (y ': x ': xs :: [k])
       = ('L1Head x (GetList1    (SinkFirst (y ': xs))) :: List1 k)

 type family GetList1 (ts :: List1 k) = (rs :: [k]) | rs -> ts where
   GetList1 ('L1Single x) = '[x]
   GetList1 ('L1Head y (x ':xs)) = y ': x ': xs
 type family GetList1Nat (ts :: List1 Nat) = (rs :: [Nat]) | rs -> ts where
   GetList1Nat ('L1Single x) = '[x]
   GetList1Nat ('L1Head y (x ': xs)) = y ': x ': xs

 type family (++) (as :: [k]) (bs :: [k]) :: [k] where
   '[] ++ bs = bs
   (a ': as) ++ bs = a ': (as ++ bs)


 ff :: Proxy k -> Proxy (as +: k) -> Proxy (k ': bs) -> Proxy (as ++ bs)
 ff _ _ _ = Proxy

 yy :: Proxy '[3,7,2]
 yy = ff (Proxy @5) (Proxy @'[3,7,5]) (Proxy @'[5,2])
 }}}

 This gives me the following error:
 {{{
 ~/TFTest.hs: 47, 21
 • Couldn't match kind ‘k’ with ‘Nat’
   When matching the kind of ‘7 : xs’
   Expected type: Proxy ((3 : (7 : xs)) +: 5)
     Actual type: Proxy '[3, 7, 5]
 • In the second argument of ‘ff’, namely ‘(Proxy @'[3, 7, 5])’
   In the expression:
     ff (Proxy @5) (Proxy @'[3, 7, 5]) (Proxy @'[5, 2])
   In an equation for ‘yy’:
       yy = ff (Proxy @5) (Proxy @'[3, 7, 5]) (Proxy @'[5, 2])
 }}}

 However, if I uncomment lines `26-27`, the code works perfectly fine!

 This behaviour feels like a bug in type checker, though I am not sure.
 If it is not, please, explain me what happens here? :)

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


More information about the ghc-tickets mailing list