{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE GADTs #-}
module Generics.MRSOP.STDiff
( module Generics.MRSOP.STDiff.Types
, apply , merge , diff
) where
import Data.Proxy
import Data.Type.Equality hiding (apply)
import Control.Monad
import Generics.MRSOP.Base
import Generics.MRSOP.STDiff.Types
import Generics.MRSOP.STDiff.Merge
import Generics.MRSOP.STDiff.Compute
applyAt :: EqHO ki
=> (At ki codes :*: NA ki (Fix ki codes)) a
-> Either String (NA ki (Fix ki codes) a)
applyAt (AtSet (Trivial a' b) :*: NA_K a)
| eqHO a' b = pure (NA_K a)
| eqHO a' a = pure (NA_K b)
| otherwise = Left "atom"
applyAt (AtFix x :*: NA_I x') = NA_I <$> applyAlmu x x'
applyAl
:: EqHO ki
=> Al ki codes xs ys
-> PoA ki (Fix ki codes) xs
-> Either String (PoA ki (Fix ki codes) ys)
applyAl A0 Nil = return Nil
applyAl (AX dx dxs) (x :* xs) =
(:*) <$> applyAt (dx :*: x) <*> applyAl dxs xs
applyAl (AIns x dxs) xs =
(x :*) <$> applyAl dxs xs
applyAl (ADel x dxs) (x' :* xs) =
if eqHO x x' then applyAl dxs xs else Left "al del"
testEquality' :: (TestEquality f)
=> f a -> f b -> Either String (a :~: b)
testEquality' x y = case testEquality x y of
Just r -> Right r
Nothing -> Left "err"
applySpine
:: EqHO ki
=> SNat ix
-> SNat iy
-> Spine ki codes (Lkup ix codes) (Lkup iy codes)
-> Rep ki (Fix ki codes) (Lkup ix codes)
-> Either String (Rep ki (Fix ki codes) (Lkup iy codes))
applySpine _ _ Scp x = return x
applySpine ix iy (SCns c1 dxs) (sop -> Tag c2 xs) = do
Refl <- testEquality' ix iy
Refl <- testEquality' c1 c2
inj c2 <$> (mapNPM applyAt (zipNP dxs xs))
applySpine _ _ (SChg c1 c2 al) (sop -> Tag c3 xs) = do
Refl <- testEquality' c1 c3
inj c2 <$> applyAl al xs
insCtx
:: (IsNat ix, EqHO ki)
=> InsCtx ki codes ix xs
-> Fix ki codes ix
-> Either String (PoA ki (Fix ki codes) xs)
insCtx (H x x2) x1 = (\xi -> NA_I xi :* x2) <$> applyAlmu x x1
insCtx (T x x2) x1 = (x :*) <$> insCtx x2 x1
delCtx
:: (EqHO ki, IsNat ix)
=> DelCtx ki codes ix xs
-> PoA ki (Fix ki codes) xs
-> Either String (Fix ki codes ix)
delCtx (H spu _) (NA_I x :* _) = applyAlmu (unAlmuMin spu) x
delCtx (T _ al) (_ :* p) = delCtx al p
applyAlmu
:: forall ki codes ix iy. (IsNat ix, IsNat iy, EqHO ki)
=> Almu ki codes ix iy
-> Fix ki codes ix
-> Either String (Fix ki codes iy)
applyAlmu (Spn spine) (Fix rep) = Fix <$> applySpine (getSNat (Proxy @ix)) (getSNat (Proxy @iy)) spine rep
applyAlmu (Ins c ctx) f@(Fix _) = Fix . inj c <$> insCtx ctx f
applyAlmu (Del c ctx) (Fix rep) = delCtx ctx <=< m2e . match c $ rep
where
m2e Nothing = Left (show "del")
m2e (Just r) = Right r
apply :: forall ki codes ix iy
. (IsNat ix, IsNat iy, EqHO ki)
=> Almu ki codes ix iy
-> Fix ki codes ix
-> Maybe (Fix ki codes iy)
apply almu x = case applyAlmu almu x of
Left _ -> Nothing
Right y -> Just y