goldfirere / ghc

Mirror of ghc repository. DO NOT SUBMIT PULL REQUESTS HERE
http://www.haskell.org/ghc/
Other
25 stars 1 forks source link

Type-level GADT inference failure #29

Open goldfirere opened 9 years ago

goldfirere commented 9 years ago
{-# LANGUAGE DataKinds, PolyKinds, GADTs, TypeOperators, TypeFamilies,
             UndecidableInstances, ScopedTypeVariables #-}
{-# OPTIONS_GHC -fwarn-unticked-promoted-constructors #-}

module SystemF where

import Data.Type.Bool
import GHC.Exts ( Any )
import Data.Type.Equality

type family a ++ b where
  '[] ++ xs2 = xs2
  (x ': xs1) ++ xs2 = x ': (xs1 ++ xs2)
infixr 5 ++

data Nat = Zero | Succ Nat

type family Pred n where
  Pred ('Succ n) = n

data Fin n where
  FZ :: Fin ('Succ n)
  FS :: Fin n -> Fin ('Succ n)

type family (a :: x) <= (f :: Fin n) :: Bool where
  'Zero <= x       = 'True
  'FZ <= x         = 'True

  x  <= 'FZ         = 'False

  'Succ a <= 'FS b = a <= b
  'FS a   <= 'FS b = a <= b

type family (a :: Nat) `NPlus` (b :: Nat) where
  'Zero `NPlus` b = b
  'Succ a `NPlus` b = 'Succ (a `NPlus` b)

type family (a :: Nat) + (f :: Fin n) :: Fin (a `NPlus` n) where
  'Zero + f = f
  'Succ a + f = 'FS (a + f)

type family FPred (f :: Fin ('Succ n)) :: Fin n where
  FPred ('FS f) = f

type family WeakenFin (f :: Fin n) :: Fin ('Succ n) where
  WeakenFin 'FZ = 'FZ
  WeakenFin ('FS f) = 'FS (WeakenFin f)

type family WeakenFinN (n :: Nat) (f :: Fin m) :: Fin (n `NPlus` m) where
  WeakenFinN 'Zero f = f
  WeakenFinN ('Succ n) f = WeakenFin (WeakenFinN n f)

type family StrengthenFin (f :: Fin ('Succ n)) :: Fin n where
  StrengthenFin 'FZ = 'FZ
  StrengthenFin ('FS f) = 'FS (StrengthenFin f)

data SFin :: Fin n -> * where
  SFZ :: SFin 'FZ
  SFS :: SFin n -> SFin ('FS n)

data Ty n where
  TVar :: Fin n -> Ty n
  TForall :: Ty ('Succ n) -> Ty n
  (:~>) :: Ty n -> Ty n -> Ty n
infixr 0 :~>

data STy :: Ty n -> * where
  STVar :: SFin n -> STy ('TVar n)
  STForall :: STy ty -> STy ('TForall ty)
  (:%~>) :: STy t1 -> STy t2 -> STy (t1 ':~> t2)
infixr 0 :%~>

data Elem :: [a] -> a -> * where
  EZ :: Elem (x ': xs) x
  ES :: Elem xs x -> Elem (y ': xs) x

type family NPlus_Succ_R' (a :: Nat) (b :: Nat) (eq :: (a `NPlus` 'Succ b) :~: ('Succ (a `NPlus` b))) :: (('Succ a `NPlus` 'Succ b) :~: ('Succ ('Succ (a `NPlus` b)))) where
  NPlus_Succ_R' a b 'Refl = 'Refl

type family NPlus_Succ_R (a :: Nat) (b :: Nat) :: (a `NPlus` 'Succ b) :~: 'Succ (a `NPlus` b) where
  NPlus_Succ_R 'Zero b = 'Refl
--  NPlus_Succ_R ('Succ a) b = 'Refl

type family TShift (cutoff :: Nat) (shift :: Nat) (ty :: Ty n) :: Ty (shift `NPlus` n) where
  TShift cutoff shift ('TVar f)
    = If (cutoff <= f) ('TVar (shift + f)) ('TVar (WeakenFinN shift f))
--  TShift cutoff shift ('TForall ty) = 'TForall (TShift ('Succ cutoff) shift ty)
--  TShift cutoff shift (a ':~> b) = (TShift shift cutoff a) ':~> (TShift shift cutoff b)
{-
type family TShiftCtx (shift :: Nat) (tys :: [Ty n]) :: [Ty ('Succ n)] where
  TShiftCtx shift '[] = '[]
  TShiftCtx shift (ty ': tys) = (TShift 'Zero shift ty ': TShiftCtx tys)

type family TSubst (var :: Fin ('Succ n1))
                   (inner_ty :: Ty n1)
                   (outer_ty :: Ty ('Succ n1))
                   :: Ty n1 where
  TSubst var inner_ty ('TVar var) = inner_ty
  TSubst var inner_ty ('TVar var') = 'TVar (If (var <= var') (FPred var') (BumpFinDown var'))
  TSubst var inner_ty ('TForall ty) = 'TForall (TSubst ('FS var) (TShift 'Zero inner_ty) ty)
  TSubst var inner_ty (a ':~> b) = TSubst var inner_ty a ':~> TSubst var inner_ty b

data Expr :: [Ty n] -> Ty n -> * where
  Var :: Elem ctx ty -> Expr ctx ty
  Abs :: Expr (arg ': ctx) res -> Expr ctx (arg ':~> res)
  App :: Expr ctx (arg ':~> res) -> Expr ctx arg -> Expr ctx res
  TAbs :: Expr (TShiftCtx ('Succ 'Zero) ctx) ty -> Expr ctx ('TForall ty)
  TApp :: Expr ctx ('TForall res) -> STy arg -> Expr ctx (TSubst 'FZ arg res)

data Length :: [a] -> * where
  LZ :: Length '[]
  LS :: Length xs -> Length (x ': xs)

tshift :: Expr ctx ty -> Expr

shift :: forall ctx ty x. Expr ctx ty -> Expr (x ': ctx) ty
shift = go LZ
  where
    go :: forall ctx0 ty. Length ctx0
       -> Expr (ctx0 ++ ctx) ty -> Expr (ctx0 ++ x ': ctx) ty
    go ctx0 (Var v) = Var (shift_var ctx0 v)
    go ctx0 (Abs body) = Abs (go (LS ctx0) body)
    go ctx0 (App e1 e2) = App (go ctx0 e1) (go ctx0 e2)
    go ctx0 (TAbs body) = TAbs (_ (go ctx0 body))

    shift_var :: forall ctx0 ty. Length ctx0
              -> Elem (ctx0 ++ ctx) ty -> Elem (ctx0 ++ x ': ctx) ty
    shift_var LZ e = ES e
    shift_var (LS _) EZ = EZ
    shift_var (LS ctx0') (ES e') = ES (shift_var ctx0' e')
-}