{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE NoStarIsType #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Math.Tensor.Safe.Proofs
  ( 
    saneTailRProof
  , singITailRProof
  , 
    saneMergeRProof
  , proofMergeLT
  , proofMergeGT
  , proofMergeIxNotEQ
  , proofMergeIxLT
  , proofMergeIxGT
  , 
    saneContractProof
  , singletonContractProof
  , contractTailDiffVProof
  , contractTailSameVNoConProof
  , contractTailSameVNoCovProof
  , contractTailSameVDiffIProof
  , contractTailSameVSameIProof
  ) where
import Math.Tensor.Safe.TH
import Data.Constraint
  ( Dict (Dict)
  , (:-) (Sub)
  )
import Unsafe.Coerce (unsafeCoerce)
import Data.Singletons.Prelude
  ( Sing, SingI
  , PEq ((==))
  , Symbol
  , Fst, Snd, Compare
  )
{-# INLINE saneTailRProof #-}
saneTailRProof :: forall (r :: Rank).Sing r -> (Sane r ~ 'True) :- (Sane (TailR r) ~ 'True)
saneTailRProof _ = Sub axiom
  where
    axiom :: Sane r ~ 'True => Dict (Sane (TailR r) ~ 'True)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE singITailRProof #-}
singITailRProof :: forall (r :: Rank).Sing r -> SingI r :- SingI (TailR r)
singITailRProof _ = Sub axiom
  where
    axiom :: SingI r => Dict (SingI (TailR r))
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE saneMergeRProof #-}
saneMergeRProof :: forall (r :: Rank) (r' :: Rank) (r'' :: Rank).
                     Sing r -> Sing r' ->
                     (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'') :- (Sane r'' ~ 'True)
saneMergeRProof _ _ = Sub axiom
  where
    axiom :: (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'') =>
             Dict (Sane r'' ~ 'True)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE proofMergeLT #-}
proofMergeLT :: forall (r :: Rank) (r' :: Rank) (r'' :: Rank).
                Sing r -> Sing r' ->
                (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
                 Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'LT)
                :- (MergeR (TailR r) r' ~ 'Just (TailR r''))
proofMergeLT _ _ = Sub axiom
  where
    axiom :: (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
              Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'LT)
             => Dict (MergeR (TailR r) r' ~ 'Just (TailR r''))
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE proofMergeIxNotEQ #-}
proofMergeIxNotEQ :: forall (r :: Rank) (r' :: Rank) (r'' :: Rank).
                     Sing r -> Sing r' ->
                     (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
                      Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'EQ)
                     :- ((IxCompare (Snd (HeadR r)) (Snd (HeadR r')) == 'EQ) ~ 'False)
proofMergeIxNotEQ _ _ = Sub axiom
  where
    axiom :: (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
             Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'EQ)
             => Dict ((IxCompare (Snd (HeadR r)) (Snd (HeadR r')) == 'EQ) ~ 'False)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE proofMergeIxLT #-}
proofMergeIxLT :: forall (r :: Rank) (r' :: Rank) (r'' :: Rank).
                  Sing r -> Sing r' ->
                  (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
                   Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'EQ,
                   IxCompare (Snd (HeadR r)) (Snd (HeadR r')) ~ 'LT)
                  :- (MergeR (TailR r) r' ~ 'Just (TailR r''))
proofMergeIxLT _ _ = Sub axiom
  where
    axiom :: (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
              Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'EQ,
              IxCompare (Snd (HeadR r)) (Snd (HeadR r')) ~ 'LT)
             => Dict (MergeR (TailR r) r' ~ 'Just (TailR r''))
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE proofMergeGT #-}
proofMergeGT :: forall (r :: Rank) (r' :: Rank) (r'' :: Rank).
                Sing r -> Sing r' ->
                (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
                 Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'GT)
                :- (MergeR r (TailR r') ~ 'Just (TailR r''))
proofMergeGT _ _ = Sub axiom
  where
    axiom :: (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
              Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'GT)
             => Dict (MergeR r (TailR r') ~ 'Just (TailR r''))
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE proofMergeIxGT #-}
proofMergeIxGT :: forall (r :: Rank) (r' :: Rank) (r'' :: Rank).
                  Sing r -> Sing r' ->
                  (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
                   Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'EQ,
                   IxCompare (Snd (HeadR r)) (Snd (HeadR r')) ~ 'GT)
                  :- (MergeR r (TailR r') ~ 'Just (TailR r''))
proofMergeIxGT _ _ = Sub axiom
  where
    axiom :: (Sane r ~ 'True, Sane r' ~ 'True, MergeR r r' ~ 'Just r'',
              Compare (Fst (HeadR r)) (Fst (HeadR r')) ~ 'EQ,
              IxCompare (Snd (HeadR r)) (Snd (HeadR r')) ~ 'GT)
             => Dict (MergeR r (TailR r') ~ 'Just (TailR r''))
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE saneContractProof #-}
saneContractProof :: forall (r :: Rank).Sing r -> (Sane r ~ 'True) :- (Sane (ContractR r) ~ 'True)
saneContractProof _ = Sub axiom
  where
    axiom :: Sane r ~ 'True => Dict (Sane (ContractR r) ~ 'True)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE singletonContractProof #-}
singletonContractProof :: forall (r :: Rank).
                          Sing r -> (TailR r ~ '[]) :- (ContractR r ~ r)
singletonContractProof _ = Sub axiom
  where
    axiom :: TailR r ~ '[] => Dict (ContractR r ~ r)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE contractTailDiffVProof #-}
contractTailDiffVProof :: forall (r :: Rank) (t :: Rank) (t' :: Rank).
                          Sing r ->
                          (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'False)
                          :- (TailR (ContractR r) ~ ContractR t)
contractTailDiffVProof _ = Sub axiom
  where
    axiom :: (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'False)
             => Dict (TailR (ContractR r) ~ ContractR t)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE contractTailSameVNoConProof #-}
contractTailSameVNoConProof :: forall (r :: Rank) (t :: Rank) (t' :: Rank) (i :: Symbol).
                               Sing r ->
                               (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'True,
                                Snd (HeadR r) ~ 'ICov i)
                               :- (TailR (ContractR r) ~ ContractR t)
contractTailSameVNoConProof _ = Sub axiom
  where
    axiom :: (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'True,
              Snd (HeadR r) ~ 'ICov i)
             => Dict (TailR (ContractR r) ~ ContractR t)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE contractTailSameVNoCovProof #-}
contractTailSameVNoCovProof :: forall (r :: Rank) (t :: Rank) (t' :: Rank) (i :: Symbol).
                               Sing r ->
                               (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'True,
                                Snd (HeadR t) ~ 'ICon i)
                               :- (TailR (ContractR r) ~ ContractR t)
contractTailSameVNoCovProof _ = Sub axiom
  where
    axiom :: (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'True,
              Snd (HeadR t) ~ 'ICon i)
             => Dict (TailR (ContractR r) ~ ContractR t)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE contractTailSameVDiffIProof #-}
contractTailSameVDiffIProof :: forall (r :: Rank) (t :: Rank) (t' :: Rank) (i :: Symbol) (j :: Symbol).
                               Sing r ->
                               (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'True,
                                Snd (HeadR r) ~ 'ICon i, Snd (HeadR t) ~ 'ICov j, (i == j) ~ 'False)
                               :- (TailR (ContractR r) ~ ContractR t)
contractTailSameVDiffIProof _ = Sub axiom
  where
    axiom :: (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'True,
              Snd (HeadR r) ~ 'ICon i, Snd (HeadR t) ~ 'ICov j, (i == j) ~ 'False)
             => Dict (TailR (ContractR r) ~ ContractR t)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))
{-# INLINE contractTailSameVSameIProof #-}
contractTailSameVSameIProof :: forall (r :: Rank) (t :: Rank) (t' :: Rank) (i :: Symbol) (j :: Symbol).
                               Sing r ->
                               (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'True,
                                Snd (HeadR r) ~ 'ICon i, Snd (HeadR t) ~ 'ICov j, (i == j) ~ 'True)
                               :- (ContractR t' ~ ContractR r)
contractTailSameVSameIProof _ = Sub axiom
  where
    axiom :: (t ~ TailR r, t' ~ TailR t, (Fst (HeadR r) == Fst (HeadR t)) ~ 'True,
              Snd (HeadR r) ~ 'ICon i, Snd (HeadR t) ~ 'ICov j, (i == j) ~ 'True)
             => Dict (ContractR t' ~ ContractR r)
    axiom = unsafeCoerce (Dict :: Dict (a ~ a))