packages feed

eliminators-0.6: tests/EqualityTypes.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module EqualityTypes where

import           Data.Kind
import           Data.Singletons.TH
import           Data.Type.Equality ((:~~:)(..))

import           Internal

data (%:~:) :: forall k (a :: k) (b :: k). a :~: b -> Type where
  SRefl :: (%:~:) Refl
type instance Sing = (%:~:)

instance SingKind (a :~: b) where
  type Demote (a :~: b) = a :~: b
  fromSing SRefl = Refl
  toSing Refl    = SomeSing SRefl

instance SingI Refl where
  sing = SRefl

-- | Christine Paulin-Mohring's version of the J rule.
(~>:~:) :: forall k (a :: k)
                  (p :: forall (y :: k). a :~: y ~> Type)
                  (b :: k) (r :: a :~: b).
           Sing r
        -> p @@ Refl
        -> p @@ r
(~>:~:) SRefl pRefl = pRefl

(~>!:~:) :: forall k (a :: k)
                   (p :: k ~> Prop)
                   (b :: k).
            a :~: b
         -> p @@ a
         -> p @@ b
(~>!:~:) Refl pRefl = pRefl

data (%:~~:) :: forall j k (a :: j) (b :: k). a :~~: b -> Type where
  SHRefl :: (%:~~:) HRefl
type instance Sing = (%:~~:)

instance SingKind (a :~~: b) where
  type Demote (a :~~: b) = a :~~: b
  fromSing SHRefl = HRefl
  toSing HRefl    = SomeSing SHRefl

instance SingI HRefl where
  sing = SHRefl

-- | Christine Paulin-Mohring's version of the J rule, but heterogeneously kinded.
(~>:~~:) :: forall j (a :: j)
                   (p :: forall z (y :: z). a :~~: y ~> Type)
                   k (b :: k) (r :: a :~~: b).
            Sing r
         -> p @@ HRefl
         -> p @@ r
(~>:~~:) SHRefl pHRefl = pHRefl

(~>!:~~:) :: forall j (a :: j)
                    (p :: forall z. z ~> Prop)
                    k (b :: k).
             a :~~: b
          -> p @@ a
          -> p @@ b
(~>!:~~:) HRefl pHRefl = pHRefl

-----

-- These newtype wrappers are needed to work around
-- https://gitlab.haskell.org/ghc/ghc/issues/9269
newtype WrappedTrans (x :: k) (e :: x :~: y) =
  WrapTrans { unwrapTrans :: forall (z :: k). y :~: z -> x :~: z }
newtype WrappedHTrans (x :: j) (e :: x :~~: (y :: k)) =
  WrapHTrans { unwrapHTrans :: forall l (z :: l). y :~~: z -> x :~~: z }

-- This is all needed to avoid impredicativity in the defunctionalization
-- symbols for WhyHReplace and WhyHLeibniz.
newtype WrappedPred = WrapPred { unwrapPred :: forall z. z ~> Type }
type family UnwrapPred (wp :: WrappedPred) :: forall z. z ~> Type where
  forall (uwp :: forall z. z ~> Type). UnwrapPred (WrapPred uwp) = uwp

$(singletons [d|
  type WhySym (a :: t) (e :: a :~: (y :: t)) =
    y :~: a :: Type

  type WhySSym (a :: t) (e :: a :~: (y :: t)) =
    Sing (Symmetry e) :: Type

  type WhyHSym (a :: j) (e :: a :~~: (y :: z)) =
    y :~~: a :: Type

  type WhySHSym (a :: j) (e :: a :~~: (y :: z)) =
    Sing (HSymmetry e) :: Type

  type family Symmetry (x :: (a :: k) :~: (b :: k)) :: b :~: a where
    Symmetry Refl = Refl

  type WhySymIdempotent (a :: t) (r :: a :~: (z :: t)) =
    Symmetry (Symmetry r) :~: r :: Type

  type family HSymmetry (x :: a :~~: b) :: b :~~: a where
    HSymmetry HRefl = HRefl

  type WhyHSymIdempotent (a :: j) (r :: a :~~: (y :: z)) =
    HSymmetry (HSymmetry r) :~: r :: Type

  type WhyTrans (x :: k) (e :: x :~: (y :: k)) =
    WrappedTrans x e :: Type

  type WhyHTrans (x :: j) (e :: x :~~: (y :: k)) =
    WrappedHTrans x e :: Type

  type family Trans (x :: a :~: b) (y :: b :~: c) :: a :~: c where
    Trans Refl Refl = Refl

  type family HTrans (x :: a :~~: b) (y :: b :~~: c) :: a :~~: c where
    HTrans HRefl HRefl = HRefl

  type WhyReplace (from :: t) (p :: t ~> Type) (e :: from :~: (y :: t)) =
    p @@ y :: Type

  type WhyHReplace (from :: j) (p :: WrappedPred) (e :: from :~~: (y :: k)) =
    UnwrapPred p @@ y :: Type

  type WhyLeibniz (f :: t ~> Type) (a :: t) (z :: t) =
    f @@ a -> f @@ z :: Type

  type WhyHLeibniz (f :: WrappedPred) (a :: j) (b :: k) =
    UnwrapPred f @@ a -> UnwrapPred f @@ b :: Type

  type WhyCong (f :: x ~> y) (a :: x) (e :: a :~: (z :: x)) =
    f @@ a :~: f @@ z :: Type

  type WhyEqIsRefl (a :: k) (e :: a :~: (z :: k)) =
    e :~~: (Refl :: a :~: a) :: Type

  type WhyHEqIsHRefl (a :: j) (e :: a :~~: (z :: k)) =
    e :~~: (HRefl :: a :~~: a) :: Type

  type WhyTransLeft (a :: k) (e :: a :~: (z :: k)) =
    Trans e Refl :~: e :: Type

  type WhyTransLeftHelper (b :: k) (e :: b :~: (z :: k)) =
    Trans (Symmetry e) Refl :~: Symmetry e :: Type

  type WhyHTransLeft (a :: j) (e :: a :~~: (z :: k)) =
    HTrans e HRefl :~: e :: Type

  type WhyHTransLeftHelper (b :: k) (e :: b :~~: (z :: j)) =
    HTrans (HSymmetry e) HRefl :~: HSymmetry e :: Type

  type WhyTransRight (a :: k) (e :: a :~: (z :: k)) =
    Trans Refl e :~: e :: Type

  type WhyHTransRight (a :: j) (e :: a :~~: (z :: k)) =
    HTrans HRefl e :~: e :: Type

  type WhyRebalance (b :: x2 :~: x3) (c :: x3 :~: x4) (a :: x1 :~: x2) =
    Trans a (Trans b c) :~: Trans (Trans a b) c :: Type

  type WhyRebalanceHelper (b :: x2 :~: x3) (c :: x3 :~: x4) (a :: x2 :~: x1) =
    Trans (Symmetry a) (Trans b c) :~: Trans (Trans (Symmetry a) b) c :: Type

  type WhyHRebalance (b :: x2 :~~: x3) (c :: x3 :~~: x4) (a :: x1 :~~: x2) =
    HTrans a (HTrans b c) :~: HTrans (HTrans a b) c :: Type

  type WhyHRebalanceHelper (b :: x2 :~~: x3) (c :: x3 :~~: x4) (a :: x2 :~~: (x1 :: k1)) =
    HTrans (HSymmetry a) (HTrans b c) :~: HTrans (HTrans (HSymmetry a) b) c :: Type
  |])

-- These newtype wrappers are needed to work around
-- https://gitlab.haskell.org/ghc/ghc/issues/9269
newtype WrappedSTrans (x :: k) (e1 :: x :~: y) =
  WrapSTrans { unwrapSTrans :: forall (z :: k) (e2 :: y :~: z).
                               Sing e2 -> Sing (Trans e1 e2) }
newtype WrappedSHTrans (x :: j) (e1 :: x :~~: (y :: k)) =
  WrapSHTrans { unwrapSHTrans :: forall l (z :: l) (e2 :: y :~~: z).
                                 Sing e2 -> Sing (HTrans e1 e2) }

$(singletons [d|
  type WhySTrans (x :: k) (e :: x :~: (y :: k)) =
    WrappedSTrans x e :: Type

  type WhySHTrans (x :: j) (e :: x :~~: (y :: k)) =
    WrappedSHTrans x e :: Type
  |])