[GHC] #12564: Type family in type pattern kind

GHC ghc-devs at haskell.org
Fri Feb 8 15:13:22 UTC 2019


#12564: Type family in type pattern kind
-------------------------------------+-------------------------------------
        Reporter:  int-index         |                Owner:  goldfire
            Type:  bug               |               Status:  new
        Priority:  high              |            Milestone:  8.4.1
       Component:  Compiler (Type    |              Version:  8.0.1
  checker)                           |             Keywords:  TypeInType,
      Resolution:                    |  TypeFamilies
Operating System:  Unknown/Multiple  |         Architecture:
 Type of failure:  GHC rejects       |  Unknown/Multiple
  valid program                      |            Test Case:
      Blocked By:  14119             |             Blocking:
 Related Tickets:                    |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by RyanGlScott):

 For anyone reading this ticket who is searching for a workaround:

 While I haven't found a general-purpose way to avoid this bug, in limited
 situations it's often possible to rewrite your type families in a way that
 shifts applications of type families from the left-hand side to the right-
 hand side. For example, GHC //does// accept this formulation of `At`:

 {{{#!hs
 {-# LANGUAGE DataKinds #-}
 {-# LANGUAGE GADTs #-}
 {-# LANGUAGE PolyKinds #-}
 {-# LANGUAGE TypeFamilies #-}
 {-# LANGUAGE TypeOperators #-}
 {-# LANGUAGE UndecidableInstances #-}

 import Data.Kind
 import Data.Type.Equality

 data N = Z | S N

 type family Len (xs :: [a]) :: N where
   Len '[] = Z
   Len (_ ': xs) = S (Len xs)

 data Vec :: N -> Type -> Type where
   VNil :: Vec Z a
   (:>) :: a -> Vec n a -> Vec (S n) a

 type family ListToVec (l :: [a]) :: Vec (Len l) a where
   ListToVec '[]    = VNil
   ListToVec (x:xs) = x :> ListToVec xs

 data Fin :: N -> Type where
   FZ :: Fin (S n)
   FS :: Fin n -> Fin (S n)

 type family At (xs :: [a]) (i :: Fin (Len xs)) :: a where
   At xs i = At' (ListToVec xs) i

 type family At' (xs :: Vec n a) (i :: Fin n) :: a where
   At' (x :> _)  FZ     = x
   At' (_ :> xs) (FS i) = At' xs i

 -- Unit tests
 test1 :: At '[True] FZ :~: True
 test1 = Refl

 test2 :: At [True, False] FZ :~: True
 test2 = Refl

 test3 :: At [True, False] (FS FZ) :~: False
 test3 = Refl
 }}}

 If you inspect the definition of `At`, you'll see why this works:

 {{{
 λ> :info At
 type family At @a (xs :: [a]) (i :: Fin (Len @a xs)) :: a where
   forall a (xs :: [a]) (i :: Fin (Len @a xs)).
     At @a xs i = At' @(Len @a xs) @a (ListToVec @a xs) i
 }}}

 Note that the left-hand side, `At @a xs i`, does not contain any immediate
 uses of `Len`. (The kind of `i` does, but thankfully, GHC doesn't consider
 that to be an illegal type synonym family application.) The other uses of
 `Len` and `ListToVec` have been quarantined off on the right-hand side,
 where GHC can't complain about them.

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


More information about the ghc-tickets mailing list