packages feed

eliminators-0.6: tests/EqualitySpec.hs

{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module EqualitySpec where

import           Data.Kind
import           Data.Singletons
import qualified Data.Type.Equality as DTE
import           Data.Type.Equality ((:~:)(..), (:~~:)(..))

import           EqualityTypes
import           Internal

import           Test.Hspec

main :: IO ()
main = hspec spec

spec :: Spec
spec = parallel $ do
  describe "sym" $ do
    let boolEq :: Bool :~: Bool
        boolEq = Refl
    it "behaves like the one from Data.Type.Equality" $ do
      sym boolEq       `shouldBe` DTE.sym boolEq
      sym (sym boolEq) `shouldBe` DTE.sym (DTE.sym boolEq)
    it "behaves like the one from Data.Type.Equality" $ do
      trans boolEq boolEq       `shouldBe` DTE.trans boolEq boolEq
      trans boolEq (sym boolEq) `shouldBe` Refl

-----

j :: forall k (p :: forall (x :: k) (y :: k). x :~: y ~> Type)
            (a :: k) (b :: k)
            (r :: a :~: b).
     Sing r
  -> (forall (x :: k). p @@ (Refl @x))
  -> p @@ r
j SRefl pRefl = pRefl @a

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

hj :: forall (p :: forall y z (w :: y) (x :: z). w :~~: x ~> Type)
             j k (a :: j) (b :: k)
             (r :: a :~~: b).
      Sing r
   -> (forall y (w :: y). p @@ (HRefl @w))
   -> p @@ r
hj SHRefl pHRefl = pHRefl @j @a

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

k :: forall k (a :: k)
            (p :: a :~: a ~> Type)
            (r :: a :~: a).
     Sing r
  -> p @@ Refl
  -> p @@ r
k SRefl pRefl = pRefl

hk :: forall k (a :: k)
             (p :: a :~~: a ~> Type)
             (r :: a :~~: a).
      Sing r
   -> p @@ HRefl
   -> p @@ r
hk SHRefl pHRefl = pHRefl

sym :: forall t (a :: t) (b :: t).
       a :~: b -> b :~: a
sym eq = withSomeSing eq $ \(singEq :: Sing r) ->
           (~>:~:) @t @a @(WhySymSym1 a) @b @r singEq Refl

sSym :: forall t (a :: t) (b :: t) (e :: a :~: b).
        Sing e -> Sing (Symmetry e)
sSym se = (~>:~:) @t @a @(WhySSymSym1 a) @b @e se SRefl

hsym :: forall j k (a :: j) (b :: k).
        a :~~: b -> b :~~: a
hsym eq = withSomeSing eq $ \(singEq :: Sing r) ->
            (~>:~~:) @j @a @(WhyHSymSym1 a) @k @b @r singEq HRefl

sHSym :: forall j k (a :: j) (b :: k) (e :: a :~~: b).
         Sing e -> Sing (HSymmetry e)
sHSym se = (~>:~~:) @j @a @(WhySHSymSym1 a) @k @b @e se SHRefl

symIdempotent :: forall t (a :: t) (b :: t)
                        (e :: a :~: b).
                 Sing e -> Symmetry (Symmetry e) :~: e
symIdempotent se = (~>:~:) @t @a @(WhySymIdempotentSym1 a) @b @e se Refl

hsymIdempotent :: forall j k (a :: j) (b :: k)
                         (e :: a :~~: b).
                  Sing e -> HSymmetry (HSymmetry e) :~: e
hsymIdempotent se = (~>:~~:) @j @a @(WhyHSymIdempotentSym1 a) @k @b @e se Refl

trans :: forall t (a :: t) (b :: t) (c :: t).
                a :~: b -> b :~: c -> a :~: c
trans eq1 eq2 = withSomeSing eq1 $ \(singEq1 :: Sing r) ->
                  unwrapTrans ((~>:~:) @t @a @(WhyTransSym1 a) @b @r
                                       singEq1 (WrapTrans id)) eq2

htrans :: forall j k l (a :: j) (b :: k) (c :: l).
                 a :~~: b -> b :~~: c -> a :~~: c
htrans eq1 eq2 = withSomeSing eq1 $ \(singEq1 :: Sing r) ->
                   unwrapHTrans ((~>:~~:) @j @a @(WhyHTransSym1 a) @k @b @r
                                          singEq1 (WrapHTrans id)) eq2

replace :: forall t (from :: t) (to :: t) (p :: t ~> Type).
           p @@ from
        -> from :~: to
        -> p @@ to
replace from eq =
  withSomeSing eq $ \(singEq :: Sing r) ->
    (~>:~:) @t @from @(WhyReplaceSym2 from p) @to @r singEq from

hreplace :: forall j k (from :: j) (to :: k)
                   (p :: forall z. z ~> Type).
            p @@ from
         -> from :~~: to
         -> p @@ to
hreplace from heq =
  withSomeSing heq $ \(singEq :: Sing r) ->
    (~>:~~:) @j @from @(WhyHReplaceSym2 from (WrapPred p)) @k @to @r singEq from

leibniz :: forall t (f :: t ~> Type) (a :: t) (b :: t).
           a :~: b
        -> f @@ a
        -> f @@ b
leibniz = replace @t @a @b @(WhyLeibnizSym2 f a) id

hleibniz :: forall (f :: forall t. t ~> Type) j k (a :: j) (b :: k).
            a :~~: b
         -> f @@ a
         -> f @@ b
hleibniz = hreplace @j @k @a @b @(WhyHLeibnizSym2 (WrapPred f) a) id

cong :: forall x y (f :: x ~> y)
               (a :: x) (b :: x).
        a :~: b
     -> f @@ a :~: f @@ b
cong eq =
  withSomeSing eq $ \(singEq :: Sing r) ->
    (~>:~:) @x @a @(WhyCongSym2 f a) @b @r singEq Refl

eqIsRefl :: forall k (a :: k) (b :: k) (e :: a :~: b).
            Sing e -> e :~~: (Refl :: a :~: a)
eqIsRefl eq = (~>:~:) @k @a @(WhyEqIsReflSym1 a) @b @e eq HRefl

heqIsHRefl :: forall j k (a :: j) (b :: k) (e :: a :~~: b).
              Sing e -> e :~~: (HRefl :: a :~~: a)
heqIsHRefl heq = (~>:~~:) @j @a @(WhyHEqIsHReflSym1 a) @k @b @e heq HRefl

transLeft :: forall j (a :: j) (b :: j) (e :: a :~: b).
             Sing e -> Trans e Refl :~: e
transLeft se = leibniz @(a :~: b) @(WhyTransLeftSym1 a)
                       @(Symmetry (Symmetry e)) @e
                       (symIdempotent se) transLeftHelper
  where
    transLeftHelper :: Trans (Symmetry (Symmetry e)) Refl
                   :~: Symmetry (Symmetry e)
    transLeftHelper = (~>:~:) @j @b @(WhyTransLeftHelperSym1 b) @a @(Symmetry e)
                              (sSym se) Refl

htransLeft :: forall j k (a :: j) (b :: k) (e :: a :~~: b).
              Sing e -> HTrans e HRefl :~: e
htransLeft se = leibniz @(a :~~: b) @(WhyHTransLeftSym1 a)
                        @(HSymmetry (HSymmetry e)) @e
                        (hsymIdempotent se) htransLeftHelper
  where
    htransLeftHelper :: HTrans (HSymmetry (HSymmetry e)) HRefl
                    :~: HSymmetry (HSymmetry e)
    htransLeftHelper = (~>:~~:) @k @b @(WhyHTransLeftHelperSym1 b) @j @a @(HSymmetry e)
                                (sHSym se) Refl

transRight :: forall j (a :: j) (b :: j) (e :: a :~: b).
              Sing e -> Trans Refl e :~: e
transRight se = (~>:~:) @j @a @(WhyTransRightSym1 a) @b @e se Refl

htransRight :: forall j k (a :: j) (b :: k) (e :: a :~~: b).
               Sing e -> HTrans HRefl e :~: e
htransRight se = (~>:~~:) @j @a @(WhyHTransRightSym1 a) @k @b @e se Refl

-- Commented out for now, since these take ages to compile :(
-- Perhaps https://gitlab.haskell.org/ghc/ghc/merge_requests/611 will make
-- things tolerable.
{-
sTrans :: forall t (a :: t) (b :: t) (c :: t)
                   (e1 :: a :~: b) (e2 :: b :~: c).
          Sing e1 -> Sing e2 -> Sing (Trans e1 e2)
sTrans se1 = unwrapSTrans $ (~>:~:) @t @a @(WhySTransSym1 a) @b @e1
                                    se1 (WrapSTrans sTransHelper)
  where
    sTransHelper :: forall (z :: t) (e' :: a :~: z).
                    Sing e' -> Sing (Trans Refl e')
    sTransHelper se' = leibniz @(a :~: z) @(TyCon1 Sing) @e' @(Trans Refl e')
                               (sym (transRight se')) se'

sHTrans :: forall j k l (a :: j) (b :: k) (c :: l)
                  (e1 :: a :~~: b) (e2 :: b :~~: c).
           Sing e1 -> Sing e2 -> Sing (HTrans e1 e2)
sHTrans se1 = unwrapSHTrans $ (~>:~~:) @j @a @(WhySHTransSym1 a) @k @b @e1
                                       se1 (WrapSHTrans sHTransHelper)
  where
    sHTransHelper :: forall m (z :: m) (e' :: a :~~: z).
                     Sing e' -> Sing (HTrans HRefl e')
    sHTransHelper se' = leibniz @(a :~~: z) @(TyCon1 Sing) @e' @(HTrans HRefl e')
                                (sym (htransRight se')) se'

rebalance :: forall j (x1 :: j) (x2 :: j) (x3 :: j) (x4 :: j)
                    (a :: x1 :~: x2) (b :: x2 :~: x3) (c :: x3 :~: x4).
             Sing a -> Sing b -> Sing c
          -> Trans a (Trans b c) :~: Trans (Trans a b) c
rebalance sa sb sc = leibniz @(x1 :~: x2) @(WhyRebalanceSym2 b c)
                             @(Symmetry (Symmetry a)) @a
                             (symIdempotent sa) rebalanceHelper
  where
    rebalanceHelper :: Trans (Symmetry (Symmetry a)) (Trans b c)
                   :~: Trans (Trans (Symmetry (Symmetry a)) b) c
    rebalanceHelper = (~>:~:) @j @x2 @(WhyRebalanceHelperSym2 b c) @x1 @(Symmetry a)
                              (sSym sa) rebalanceBC

    rebalanceBC :: Trans Refl (Trans b c) :~: Trans (Trans Refl b) c
    rebalanceBC = trans (transRight (sTrans sb sc)) transRightBC

    transRightBC :: Trans b c :~: Trans (Trans Refl b) c
    transRightBC = cong @(x2 :~: x3) @(x2 :~: x4) @(FlipSym2 TransSym0 c)
                        @b @(Trans Refl b)
                        (sym (transRight sb))

hrebalance :: forall k1 k2 k3 k4 (x1 :: k1) (x2 :: k2) (x3 :: k3) (x4 :: k4)
                     (a :: x1 :~~: x2) (b :: x2 :~~: x3) (c :: x3 :~~: x4).
              Sing a -> Sing b -> Sing c
           -> HTrans a (HTrans b c) :~: HTrans (HTrans a b) c
hrebalance sa sb sc = leibniz @(x1 :~~: x2) @(WhyHRebalanceSym2 b c)
                              @(HSymmetry (HSymmetry a)) @a
                              (hsymIdempotent sa) hrebalanceHelper
  where
    hrebalanceHelper :: HTrans (HSymmetry (HSymmetry a)) (HTrans b c)
                    :~: HTrans (HTrans (HSymmetry (HSymmetry a)) b) c
    hrebalanceHelper = (~>:~~:) @k2 @x2 @(WhyHRebalanceHelperSym2 b c)
                                @k1 @x1 @(HSymmetry a)
                                (sHSym sa) hrebalanceBC

    hrebalanceBC :: HTrans HRefl (HTrans b c) :~: HTrans (HTrans HRefl b) c
    hrebalanceBC = trans (htransRight (sHTrans sb sc)) htransRightBC

    htransRightBC :: HTrans b c :~: HTrans (HTrans HRefl b) c
    htransRightBC = cong @(x2 :~~: x3) @(x2 :~~: x4) @(FlipSym2 HTransSym0 c)
                         @b @(HTrans HRefl b)
                         (sym (htransRight sb))
-}