module Control.SessionTypes.Normalize (
Normalize(..),
Flatten(..),
ElimRec(..),
) where
import Control.SessionTypes.STTerm
import Control.SessionTypes.Types
import Data.Proxy (Proxy (..))
class Normalize s s'' | s -> s'' where
normalize :: Monad m => STTerm m s ('Cap '[] Eps) a -> STTerm m s'' ('Cap '[] Eps) a
instance (Flatten s s', ElimRec s' s'') => Normalize s s'' where
normalize = elimRec . flatten
class ElimRec s s' | s -> s' where
elimRec :: Monad m => STTerm m s r a -> STTerm m s' r a
instance (el ~ ElimRecAllPath s, ElimRec' s s' el) => ElimRec s s' where
elimRec = elimRec' (Proxy :: Proxy el)
class ElimRec' s s' (rml :: Cap Bool) | s rml -> s' where
elimRec' :: Monad m => Proxy rml -> STTerm m s r a -> STTerm m s' r a
instance ElimRec' ('Cap ctx r) ('Cap ctx' r') rml =>
ElimRec' ('Cap ctx (a :!> r)) ('Cap ctx' (a :!> r')) rml where
elimRec' rml (Send a r) = Send a $ elimRec' rml r
instance ElimRec' ('Cap ctx r) ('Cap ctx' r') rml =>
ElimRec' ('Cap ctx (a :?> r)) ('Cap ctx' (a :?> r')) rml where
elimRec' rml (Recv r) = Recv $ \a -> elimRec' rml (r a)
instance ElimRec' ('Cap ctx s)
('Cap ctx' s')
('Cap rmctx rm) =>
ElimRec' ('Cap ctx (Sel '[s]))
('Cap ctx' (Sel '[s']))
('Cap rmctx (Sel '[rm])) where
elimRec' _ (Sel1 s) = Sel1 $ elimRec' (Proxy :: Proxy ('Cap rmctx rm)) s
instance (ElimRec' ('Cap ctx s)
('Cap ctx' s')
('Cap rmctx rm),
ElimRec' ('Cap ctx (Sel (t ': xs)))
('Cap ctx' (Sel (t' ': xs')))
('Cap rmctx (Sel rmxs))) =>
ElimRec' ('Cap ctx (Sel (s ': t ': xs)))
('Cap ctx' (Sel (s' ': t' ': xs')))
('Cap rmctx (Sel (rm ': rmxs))) where
elimRec' _ (Sel1 s) = Sel1 $ elimRec' (Proxy :: Proxy ('Cap rmctx rm)) s
elimRec' _ (Sel2 xs) = Sel2 $ elimRec' (Proxy :: Proxy ('Cap rmctx (Sel rmxs))) xs
instance ElimRec' ('Cap ctx s)
('Cap ctx' s')
('Cap rmctx rm) =>
ElimRec' ('Cap ctx (Off '[s]))
('Cap ctx' (Off '[s']))
('Cap rmctx (Off '[rm])) where
elimRec' _ (OffZ s) = OffZ $ elimRec' (Proxy :: Proxy ('Cap rmctx rm)) s
instance (ElimRec' ('Cap ctx s) ('Cap ctx' s') ('Cap rmctx rm),
ElimRec' ('Cap ctx (Off (t ': xs)))
('Cap ctx' (Off (t' ': xs')))
('Cap rmctx (Off rmxs))) =>
ElimRec' ('Cap ctx (Off (s ': t ': xs)))
('Cap ctx' (Off (s' ': t' ': xs')))
('Cap rmctx (Off (rm ': rmxs))) where
elimRec' _ (OffS s xs) =
OffS (elimRec' (Proxy :: Proxy ('Cap rmctx rm)) s)
(elimRec' (Proxy :: Proxy ('Cap rmctx (Off rmxs))) xs)
instance (ElimRec' ('Cap (s ': ctx) s)
('Cap (s' ': ctx') s')
('Cap (rml ': rmctx) rml)) =>
ElimRec' ('Cap ctx (R s))
('Cap ctx' (R s'))
('Cap rmctx ('True :!> rml)) where
elimRec' _ (Rec s) = Rec $ elimRec' (Proxy :: Proxy ('Cap (rml ': rmctx) rml)) s
instance (ElimRec' ('Cap (s ': ctx) s)
('Cap ctx' s')
('Cap rmctx rml)) =>
ElimRec' ('Cap ctx (R s))
('Cap ctx' s')
('Cap rmctx ('False :!> rml)) where
elimRec' _ (Rec s) = elimRec' (Proxy :: Proxy ('Cap rmctx rml)) s
instance (ApplyElimRecPath t rm' ~ t',
ElimRec' ('Cap ctx s)
('Cap ctx' s')
('Cap rmctx rml)) =>
ElimRec' ('Cap (t ': ctx) (Wk s))
('Cap (t' ': ctx') (Wk s'))
('Cap (rm' ': rmctx) ('True :!> rml)) where
elimRec' _ (Weaken s) = Weaken $ elimRec' (Proxy :: Proxy ('Cap rmctx rml)) s
instance (ElimRec' ('Cap ctx s)
('Cap ctx' s')
('Cap rmctx rml)) =>
ElimRec' ('Cap (t ': ctx) (Wk s))
('Cap ctx' s')
('Cap rmctx ('False :!> rml)) where
elimRec' _ (Weaken s) = elimRec' (Proxy :: Proxy ('Cap rmctx rml)) s
instance ElimRec' ('Cap (s ': ctx) s)
('Cap (s' ': ctx') s')
('Cap (rm ': rmctx) rm) =>
ElimRec' ('Cap (s ': ctx) V)
('Cap (s' ': ctx') V)
('Cap (rm ': rmctx) V) where
elimRec' _ (Var s) = Var $ elimRec' (Proxy :: Proxy ('Cap (rm ': rmctx) rm)) s
instance ElimRec' ('Cap '[] Eps) ('Cap '[] Eps) ('Cap '[] Eps) where
elimRec' _ (Ret a) = Ret a
elimRec' _ (Lift m) = error "was a lift"
type family ElimRecAllPath c where
ElimRecAllPath ('Cap ctx s) = 'Cap (MapElimRecAllPath ctx Z) (ElimRecAllPathST s Z)
type family ElimRecAllPathST s n where
ElimRecAllPathST (a :!> r) n = ElimRecAllPathST r n
ElimRecAllPathST (a :?> r) n = ElimRecAllPathST r n
ElimRecAllPathST (Sel xs) n = Sel (MapElimRecAllPath xs n)
ElimRecAllPathST (Off xs) n = Off (MapElimRecAllPath xs n)
ElimRecAllPathST (R s) n = KeepRPath (R s) (HasPathToV s (S Z)) n
ElimRecAllPathST (Wk s) (S n) = KeepWkPath (Wk s) (HasPathToV s n) (S n)
ElimRecAllPathST (Wk s) n = 'False :!> ElimRecAllPathST s n
ElimRecAllPathST V n = V
ElimRecAllPathST Eps n = Eps
type family MapElimRecAllPath xs n where
MapElimRecAllPath '[] n = '[]
MapElimRecAllPath (s ': xs) n = ElimRecAllPathST s n ': MapElimRecAllPath xs n
type family KeepRPath s b n where
KeepRPath (R s) 'True n = ('True :!> (ElimRecAllPathST s (S n)))
KeepRPath (R s) 'False n = ('False :!> ((ElimRecAllPathST s n) `MergePath` (DeleteWkPath s (S Z) n)))
type family KeepWkPath s b n where
KeepWkPath (Wk s) 'True (S n) = ('True :!> (ElimRecAllPathST s n))
KeepWkPath (Wk s) 'False n = ('True :!> ElimRecAllPathST s (S n))
type family HasPathToV s n :: Bool where
HasPathToV (a :!> r) n = HasPathToV r n
HasPathToV (a :?> r) n = HasPathToV r n
HasPathToV (Sel '[s]) n = HasPathToV s n
HasPathToV (Sel (s ': xs)) n = HasPathToV s n `Or` HasPathToV (Sel xs) n
HasPathToV (Off '[s]) n = HasPathToV s n
HasPathToV (Off (s ': xs)) n = HasPathToV s n `Or` HasPathToV (Off xs) n
HasPathToV (R s) n = HasPathToV s (S n)
HasPathToV (Wk s) (S n) = HasPathToV s n
HasPathToV (Wk s) n = 'False
HasPathToV V (S Z) = 'True
HasPathToV V n = 'False
HasPathToV Eps n = 'False
type family DeleteWkPath s n k where
DeleteWkPath (a :!> r) n k = DeleteWkPath r n k
DeleteWkPath (a :?> r) n k = DeleteWkPath r n k
DeleteWkPath (Sel xs) n k = Sel (MapDeleteWkPath xs n k)
DeleteWkPath (Off xs) n k = Off (MapDeleteWkPath xs n k)
DeleteWkPath (R s) n k = 'True :!> (DeleteWkPath s (S n) (S k))
DeleteWkPath (Wk Eps) (S Z) (S Z) = 'True :!> Eps
DeleteWkPath (Wk s) (S Z) k = 'False :!> Eps
DeleteWkPath (Wk s) (S n) (S k) = 'True :!> (DeleteWkPath s n k)
DeleteWkPath V n k = V
DeleteWkPath Eps n k = Eps
type family MapDeleteWkPath xs n k where
MapDeleteWkPath '[] n k = '[]
MapDeleteWkPath (s ': xs) n k = DeleteWkPath s n k ': MapDeleteWkPath xs n k
type family MergePath l r where
MergePath (b1 :!> l) (b2 :!> r) = Not (Not b1 `Or` Not b2) :!> MergePath l r
MergePath (Sel xs) (Sel ys) = Sel (MapMergePath xs ys)
MergePath (Off xs) (Off ys) = Off (MapMergePath xs ys)
MergePath Eps s = s
MergePath s Eps = s
MergePath V s = s
MergePath s V = s
type family MapMergePath l r where
MapMergePath '[] '[] = '[]
MapMergePath (s ': xs) (r ': ys) = MergePath s r ': MapMergePath xs ys
type family ApplyElimRecPath s ml where
ApplyElimRecPath (a :!> r) ml = a :!> ApplyElimRecPath r ml
ApplyElimRecPath (a :?> r) ml = a :?> ApplyElimRecPath r ml
ApplyElimRecPath (Sel xs) (Sel ml) = Sel (MapApplyElimRecPath xs ml)
ApplyElimRecPath (Off xs) (Off ml) = Off (MapApplyElimRecPath xs ml)
ApplyElimRecPath (R s) ('True :!> ml) = R (ApplyElimRecPath s ml)
ApplyElimRecPath (R s) ('False :!> ml) = ApplyElimRecPath s ml
ApplyElimRecPath (Wk s) ('True :!> ml) = Wk (ApplyElimRecPath s ml)
ApplyElimRecPath (Wk s) ('False :!> ml) = ApplyElimRecPath s ml
ApplyElimRecPath s ml = s
type family MapApplyElimRecPath xs ml where
MapApplyElimRecPath '[] '[] = '[]
MapApplyElimRecPath (s ': xs) (m ': ml) = ApplyElimRecPath s m ': MapApplyElimRecPath xs ml
class Flatten s s' | s -> s' where
flatten :: Monad m => STTerm m s r a -> STTerm m s' r a
instance (rwl ~ ListRewrites s, Flatten' s s' rwl) => Flatten s s' where
flatten = flatten' (Proxy :: Proxy rwl)
class Flatten' s s' rwl | s rwl -> s' where
flatten' :: Monad m => Proxy rwl -> STTerm m s r a -> STTerm m s' r a
instance Flatten' ('Cap ctx (Sel ys))
('Cap ctx' (Sel ys'))
('Cap nctx rwl) =>
Flatten' ('Cap ctx (Sel '[Sel ys]))
('Cap ctx' (Sel ys'))
('Cap nctx ((Sel '[ 'True :!> rwl]))) where
flatten' _ (Sel1 s) = flatten' (Proxy :: Proxy ('Cap nctx rwl)) s
instance (Flatten' ('Cap ctx (Sel '[y]))
('Cap ctx' (Sel '[y']))
('Cap nctx rw_y),
Flatten' ('Cap ctx (Sel (x ': xs)))
('Cap ctx' (Sel (x' ': xs')))
('Cap nctx (Sel rw_xs))) =>
Flatten' ('Cap ctx (Sel (Sel '[y] ': x ': xs)))
('Cap ctx' (Sel (y' ': x' ': xs')))
('Cap nctx (Sel ('True :!> rw_y ': rw_xs))) where
flatten' _ (Sel1 s) =
case flatten' (Proxy :: Proxy ('Cap nctx rw_y)) s of
Sel1 s' -> Sel1 s'
flatten' _ (Sel2 s) = Sel2 $ flatten' (Proxy :: Proxy ('Cap nctx (Sel rw_xs))) s
instance (Flatten' ('Cap ctx (Sel '[s]))
('Cap ctx' (Sel '[s']))
('Cap nctx (Sel '[rw_s])),
Flatten' ('Cap ctx (Sel (Sel (z ': ys) ': x ': xs)))
('Cap ctx' (Sel (z' ': xss)))
('Cap nctx (Sel (True :!> (Sel rw_ys) ': rw_xss)))) =>
Flatten' ('Cap ctx (Sel (Sel (s ': z ': ys) ': x ': xs)))
('Cap ctx' (Sel (s' ': z' ': xss)))
('Cap nctx (Sel ('True :!> Sel (rw_s ': rw_ys) ': rw_xss))) where
flatten' _ (Sel1 (Sel1 s)) = Sel1 $ singleSel (Sel1 s) (Proxy :: Proxy ('Cap nctx (Sel '[rw_s])))
flatten' _ (Sel1 (Sel2 s)) = Sel2 $ flatten' (Proxy :: Proxy ('Cap nctx (Sel (True :!> Sel rw_ys ': rw_xss))))
(instSelApp (Sel1 s) (Proxy :: Proxy (x ': xs)))
flatten' _ (Sel2 s) = Sel2 $ flatten' (Proxy :: Proxy ('Cap nctx (Sel (True :!> Sel rw_ys ': rw_xss))))
(instSelPrep (Proxy :: Proxy (Sel (z ': ys))) s)
singleSel :: Monad m => Flatten' ('Cap ctx (Sel '[s])) ('Cap ctx' (Sel '[s'])) ('Cap nctx (Sel '[rw_s])) =>
STTerm m ('Cap ctx (Sel '[s])) r a -> Proxy ('Cap nctx (Sel '[rw_s])) -> STTerm m ('Cap ctx' s') r a
singleSel st p = case flatten' p st of
(Sel1 s') -> s'
instSelApp :: STTerm m ('Cap ctx (Sel '[x])) r a -> Proxy ys -> STTerm m ('Cap ctx (Sel (x ': ys))) r a
instSelApp (Sel1 s) _ = Sel1 s
instSelPrep :: Proxy y -> STTerm m ('Cap ctx (Sel (x ': xs))) r a -> STTerm m ('Cap ctx (Sel (y ': x ': xs))) r a
instSelPrep _ s = Sel2 s
instance Flatten' ('Cap ctx (Off ys))
('Cap ctx' (Off ys'))
('Cap nctx rwl) =>
Flatten' ('Cap ctx (Off '[Off ys]))
('Cap ctx' (Off ys'))
('Cap nctx (Off '[ 'True :!> rwl])) where
flatten' _ (OffZ s) = flatten' (Proxy :: Proxy ('Cap nctx rwl)) s
instance (Flatten' ('Cap ctx (Off '[s]))
('Cap ctx' (Off '[s']))
('Cap nctx rwl_s),
Flatten' ('Cap ctx (Off (x ': xs)))
('Cap ctx' (Off (x' ': xs')))
('Cap nctx (Off rwl_xs))) =>
Flatten' ('Cap ctx (Off (Off '[s] ': x ': xs)))
('Cap ctx' (Off (s' ': x' ': xs')))
('Cap nctx (Off ('True :!> rwl_s ': rwl_xs))) where
flatten' _ (OffS (OffZ s) xs) =
case flatten' (Proxy :: Proxy ('Cap nctx rwl_s)) (OffZ s) of
(OffZ s') -> OffS s' (flatten' (Proxy :: Proxy ('Cap nctx (Off rwl_xs))) xs)
instance (Flatten' ('Cap ctx (Off '[s]))
('Cap ctx' (Off '[s']))
('Cap nctx (Off '[rwl_s])),
Flatten' ('Cap ctx (Off (Off (z ': ys) ': x ': xs)))
('Cap ctx' (Off (z' ': xss)))
('Cap nctx (Off ('True :!> (Off rwl_ys) ': rw_xs)))) =>
Flatten' ('Cap ctx (Off (Off (s ': z ': ys) ': x ': xs)))
('Cap ctx' (Off (s' ': z' ': xss)))
('Cap nctx (Off ('True :!> (Off (rwl_s ': rwl_ys)) ': rw_xs))) where
flatten' _ (OffS (OffS s ys) xs) =
case flatten' (Proxy :: Proxy ('Cap nctx (Off '[rwl_s]))) (OffZ s) of
OffZ s' -> OffS s' $ flatten' (Proxy :: Proxy ('Cap nctx (Off ('True :!> (Off rwl_ys) ': rw_xs)))) (OffS ys xs)
instance Flatten' ('Cap ctx s)
('Cap ctx' s')
('Cap nctx rwl) =>
Flatten' ('Cap ctx (Sel '[s]))
('Cap ctx' (Sel '[s']))
('Cap nctx (Sel '[ 'False :!> rwl])) where
flatten' _ (Sel1 s) = Sel1 $ flatten' (Proxy :: Proxy ('Cap nctx rwl)) s
instance (Flatten' ('Cap ctx s)
('Cap ctx' s')
('Cap nctx rw_s),
Flatten' ('Cap ctx (Sel (r ': xs)))
('Cap ctx' (Sel (r' ': xs')))
('Cap nctx (Sel rw_xs))) =>
Flatten' ('Cap ctx (Sel (s ': r ': xs)))
('Cap ctx' (Sel (s' ': r' ': xs')))
('Cap nctx (Sel ('False :!> rw_s ': rw_xs))) where
flatten' _ (Sel1 s) = Sel1 $ flatten' (Proxy :: Proxy ('Cap nctx rw_s)) s
flatten' _ (Sel2 s) = Sel2 $ flatten' (Proxy :: Proxy ('Cap nctx (Sel rw_xs))) s
instance Flatten' ('Cap ctx s)
('Cap ctx' s')
('Cap nctx rwl) =>
Flatten' ('Cap ctx (Off '[s]))
('Cap ctx' (Off '[s']))
('Cap nctx (Off '[ 'False :!> rwl])) where
flatten' _ (OffZ s) = OffZ $ flatten' (Proxy :: Proxy ('Cap nctx rwl)) s
instance (Flatten' ('Cap ctx s)
('Cap ctx' s')
('Cap nctx rwl_s),
Flatten' ('Cap ctx (Off (t ': xs)))
('Cap ctx' (Off (t' ': xs')))
('Cap nctx (Off rwl_r))) =>
Flatten' ('Cap ctx (Off (s ': t ': xs)))
('Cap ctx' (Off (s' ': t' ': xs')))
('Cap nctx (Off ('False :!> rwl_s ': rwl_r))) where
flatten' _ (OffS s xs) =
OffS (flatten' (Proxy :: Proxy ('Cap nctx rwl_s)) s)
(flatten' (Proxy :: Proxy ('Cap nctx (Off rwl_r))) xs)
instance Flatten' ('Cap ctx r)
('Cap ctx' r')
rwl =>
Flatten' ('Cap ctx (a :!> r))
('Cap ctx' (a :!> r'))
rwl where
flatten' p (Send a (Lift m)) = Send a $ Lift $ do
st <- m
return $ flatten' p st
flatten' p (Send a r) = Send a $ flatten' p r
instance Flatten' ('Cap ctx r)
('Cap ctx' r')
rwl =>
Flatten' ('Cap ctx (a :?> r))
('Cap ctx' (a :?> r'))
rwl where
flatten' p (Recv r) = Recv $ \x ->
case r x of
(Lift m) -> Lift $ do
st <- m
return $ flatten' p st
_ -> flatten' p $ r x
instance Flatten' ('Cap (s ': ctx) s)
('Cap (s' ': ctx') s')
('Cap (norm ': nctx) norm) =>
Flatten' ('Cap ctx (R s))
('Cap ctx' (R s'))
('Cap nctx norm) where
flatten' _ (Rec s) = Rec $ flatten' (Proxy :: Proxy ('Cap (norm ': nctx) norm)) s
instance (RewriteTypes t ~ t',
Flatten' ('Cap ctx s)
('Cap ctx' s')
('Cap nctx norm)) =>
Flatten' ('Cap (t ': ctx) (Wk s))
('Cap (t' ': ctx') (Wk s'))
('Cap (k ': nctx) norm) where
flatten' _ (Weaken s) = Weaken $ flatten' (Proxy :: Proxy ('Cap nctx norm)) s
instance Flatten' ('Cap (s ': ctx) s)
('Cap (s' ': ctx') s')
('Cap (norm ': nctx) norm) =>
Flatten' ('Cap (s ': ctx) V)
('Cap (s' ': ctx') V)
('Cap (norm ': nctx) V) where
flatten' _ (Var s) = Var $ flatten' (Proxy :: Proxy ('Cap (norm ': nctx) norm)) s
instance Flatten' ('Cap ctx Eps) ('Cap ctx Eps) ('Cap nctx Eps) where
flatten' _ (Ret a) = Ret a
type family ListRewrites c where
ListRewrites ('Cap ctx s) = 'Cap (MapListRewritesCtx ctx) (ListRewritesST s)
type family MapListRewritesCtx ctx where
MapListRewritesCtx '[] = '[]
MapListRewritesCtx (s ': xs) = ListRewritesST s ': MapListRewritesCtx xs
type family ListRewritesST s where
ListRewritesST (Sel xs) = Sel (RewriteFlatten (MapListRewritesCtx xs))
ListRewritesST (Off xs) = Off (RewriteFlatten (MapListRewritesCtx xs))
ListRewritesST (a :!> r) = ListRewritesST r
ListRewritesST (a :?> r) = ListRewritesST r
ListRewritesST (R s) = ListRewritesST s
ListRewritesST (Wk s) = ListRewritesST s
ListRewritesST V = V
ListRewritesST Eps = Eps
type family RewriteFlatten s where
RewriteFlatten '[] = '[]
RewriteFlatten (Sel xs ': ys) = ('True :!> Sel xs) ': RewriteFlatten ys
RewriteFlatten (Off xs ': ys) = ('True :!> Off xs) ': RewriteFlatten ys
RewriteFlatten (s ': ys) = ('False :!> s) ': RewriteFlatten ys
type family RewriteTypes s where
RewriteTypes (a :!> r) = a :!> RewriteTypes r
RewriteTypes (a :?> r) = a :?> RewriteTypes r
RewriteTypes (Sel (Sel xs ': ys)) = RewriteTypes (Sel (xs `Append` ys))
RewriteTypes (Sel (x ': xs)) = Sel (x ': MapRewriteTypes xs)
RewriteTypes (Off (Off xs ': ys)) = RewriteTypes (Off (xs `Append` ys))
RewriteTypes (Off (x ': xs)) = Off (x ': MapRewriteTypes xs)
RewriteTypes (R s) = R (RewriteTypes s)
RewriteTypes (Wk s) = Wk (RewriteTypes s)
RewriteTypes V = V
RewriteTypes Eps = Eps
type family MapRewriteTypes xs where
MapRewriteTypes '[] = '[]
MapRewriteTypes (s ': xs) = RewriteTypes s ': MapRewriteTypes xs