{-# LANGUAGE FlexibleContexts,FlexibleInstances,GADTs,DataKinds, PolyKinds, KindSignatures #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE TypeOperators #-}
module Resin.Binders.Tree.Internal(
IxEq(..)
,Inject(..)
,Extract(..)
,TreeEq(..)
,treeElimination
,rightExtendInject
,leftExtendExtract
,jumpDepthInject
,jumpDepthExtract
) where
import Numeric.Natural
import Data.Semigroupoid
import Unsafe.Coerce (unsafeCoerce)
import Data.Type.Equality
data IxEq :: (k -> * ) -> k -> k -> * where
PolyRefl :: IxEq f i i
MonoRefl :: forall f i . f i -> IxEq f i i
instance TestEquality f => TestEquality (IxEq f i) where
testEquality (MonoRefl f1) (MonoRefl f2) = testEquality f1 f2
testEquality (PolyRefl )(MonoRefl _f2) = Just Refl
testEquality (MonoRefl _f1) (PolyRefl ) = Just Refl
testEquality (PolyRefl ) (PolyRefl ) = Just Refl
data Inject :: (k -> * ) -> k -> k -> * where
InjectRefl :: forall f a b . IxEq f a b-> Inject f a b
CompactCompose :: forall f i j . (IxEq f i i) -> (IxEq f j j ) -> Natural -> Inject f i j
rightExtendInject :: Inject p a b -> p c -> Inject p a c
rightExtendInject (InjectRefl PolyRefl) rP = CompactCompose PolyRefl (MonoRefl rP) 1
rightExtendInject (InjectRefl (MonoRefl f)) rP = CompactCompose (MonoRefl f) (MonoRefl rP) 1
rightExtendInject (CompactCompose pa _pb n) rP = CompactCompose pa (MonoRefl rP) (n+1 )
leftExtendExtract :: p a -> Extract p b c -> Extract p a c
leftExtendExtract p (Dual inj) = Dual (rightExtendInject inj p)
jumpDepthInject :: Natural -> p c -> Inject p a b -> Inject p a c
jumpDepthInject plus pc (InjectRefl PolyRefl) = CompactCompose PolyRefl (MonoRefl pc) (1 + plus)
jumpDepthInject plus pc (InjectRefl (MonoRefl pa)) = CompactCompose (MonoRefl pa) (MonoRefl pc) (1 + plus)
jumpDepthInject plus pc (CompactCompose pa _pb n) = CompactCompose pa (MonoRefl pc) (n + plus + 1 )
jumpDepthExtract :: Natural -> Extract p b c -> p a -> Extract p a c
jumpDepthExtract plus (Dual cc) pc = Dual (jumpDepthInject plus pc cc)
instance Semigroupoid (Inject f) where
(InjectRefl (MonoRefl _p)) `o` (!f) = f
(InjectRefl (PolyRefl)) `o` (!f) = f
(CompactCompose in1 out1 size) `o` (InjectRefl (PolyRefl)) = CompactCompose in1 out1 size
(CompactCompose in1 out1 size) `o` (InjectRefl (MonoRefl !_p)) = CompactCompose in1 out1 size
(CompactCompose _cmiddle2 cout sizeleft)
`o` (CompactCompose cin _cmiddle1 sizeright) = CompactCompose cin cout (sizeright + sizeleft)
newtype Extract :: (k -> * ) -> k -> k -> * where
Dual :: ((Inject f) b a ) -> Extract f a b
instance Semigroupoid (Extract f) where
o = \ (Dual l) (Dual r) -> Dual $ r `o` l
data TreeEq :: (k -> * ) -> k -> k -> * where
TreeInject :: Inject f a b -> TreeEq f a b
TreeExtract :: Extract f a b -> TreeEq f a b
TreeRefl :: TreeEq f c c
treeElimination :: TestEquality f => Inject f a b -> Extract f b c-> (TreeEq f a c)
treeElimination (InjectRefl PolyRefl) (Dual (InjectRefl PolyRefl)) = TreeRefl
treeElimination (InjectRefl (MonoRefl _p1)) (Dual (InjectRefl PolyRefl)) = TreeRefl
treeElimination (InjectRefl PolyRefl) (Dual (InjectRefl (MonoRefl _p2))) = TreeRefl
treeElimination (InjectRefl (MonoRefl _p1)) (Dual (InjectRefl(MonoRefl _p2))) = TreeRefl
treeElimination (CompactCompose fa _fb1 n1) (Dual (CompactCompose fc _fb2 n2)) =
case (compare n1 n2, max n1 n2 - min n1 n2) of
(EQ, _ )-> (unsafeCoerce TreeRefl) :: TreeEq f a c
(GT, m )-> TreeInject (CompactCompose fa fc m)
(LT, m ) -> TreeExtract (Dual (CompactCompose fc fa m))
treeElimination (InjectRefl p@(PolyRefl))
d@(Dual (CompactCompose _fc _fb _n)) = treeElimination (CompactCompose p p 0) d
treeElimination (InjectRefl p@(MonoRefl _))
d@(Dual (CompactCompose _fc _fb _n)) = treeElimination (CompactCompose p p 0) d
treeElimination d@( CompactCompose _fc _fb _n)
(Dual (InjectRefl p@(PolyRefl))) = treeElimination d (Dual (CompactCompose p p 0))
treeElimination d@(CompactCompose _fc _fb _n)
(Dual (InjectRefl p@(MonoRefl _))) = treeElimination d (Dual (CompactCompose p p 0))