summaryrefslogtreecommitdiff
path: root/src/Obs/NormalForm
diff options
context:
space:
mode:
Diffstat (limited to 'src/Obs/NormalForm')
-rw-r--r--src/Obs/NormalForm/Normalise.idr714
1 files changed, 489 insertions, 225 deletions
diff --git a/src/Obs/NormalForm/Normalise.idr b/src/Obs/NormalForm/Normalise.idr
index ed06fa2..2ea6296 100644
--- a/src/Obs/NormalForm/Normalise.idr
+++ b/src/Obs/NormalForm/Normalise.idr
@@ -25,11 +25,15 @@ LogNormalForm : Type -> Sorted.Family Relevance
LogNormalForm ann b ctx = Logging ann (NormalForm b ctx)
0
+LogDeclForm : Type -> Unsorted.Family Relevance
+LogDeclForm ann ctx = Logging ann (DeclForm ctx)
+
+0
LogNormalForm' : Type -> Sorted.Family Relevance
LogNormalForm' ann b ctx = Either (Logging ann (NormalForm b ctx)) (Elem b ctx)
-- Copied and specialised from Obs.Substitution
-lift : (ctx : List (r ** (String, (s ** relevance s = r))))
+lift : (ctx : List (r ** Maybe String))
-> Map ctx' (LogNormalForm' ann) ctx''
-> Map (map DPair.fst ctx ++ ctx') (LogNormalForm' ann) (map DPair.fst ctx ++ ctx'')
lift [] f = f
@@ -42,202 +46,467 @@ lift ((s ** y) :: ctx) f = add (LogNormalForm' ann)
subst' : NormalForm ~|> Hom (LogNormalForm' ann) (LogNormalForm ann)
export
-doApp : {domain : _} ->
- NormalForm (function domain codomain) ctx ->
- NormalForm domain ctx ->
- LogNormalForm ann codomain ctx
-doApp (Ntrl t) u = pure (Ntrl $ App _ t u)
-doApp (Cnstr (Lambda s var t)) u = inScope "doApp" $ do
- trace $ pretty {ann} "substituting" <++> pretty u <+> softline <+> pretty "for \{var} in" <++> pretty t
- let Yes Refl = decEq domain (relevance s)
+subst1 : {s' : _} -> NormalForm s ctx -> NormalForm s' (s :: ctx) -> LogNormalForm ann s' ctx
+subst1 t u = subst' u (add (LogNormalForm' ann) (Left $ pure t) Right)
+
+export
+map1 : {s' : _} ->
+ NormalForm s (s :: ctx) ->
+ NormalForm s' (s :: ctx) ->
+ LogNormalForm ann s' (s :: ctx)
+map1 t u = subst' u (add (LogNormalForm' ann) (Left $ pure t) (Right . There))
+
+export
+doApp : {domainRel : _} ->
+ (fun : NormalForm (function domainRel codomainRel) ctx) ->
+ (arg : NormalForm domainRel ctx) ->
+ LogNormalForm ann codomainRel ctx
+
+doApp (Ntrl fun) arg = pure $ Ntrl $ App {argRel = _, fun, arg}
+doApp (Cnstr (Lambda {domainRel = domainRel', var, body})) arg = do
+ let Yes Refl = decEq domainRel domainRel'
| No _ => fatal "internal relevance mismatch"
- subst' t (add (LogNormalForm' ann) (Left $ pure u) Right)
-doApp (Cnstr t) u = inScope "wrong constructor for apply" $ fatal t
-doApp Irrel u = pure Irrel
+
+ subst1 arg body
+doApp (Cnstr t) arg = inScope "wrong constructor for apply" $ fatal t
+doApp Irrel arg = pure Irrel
export
-doFst : (fst, snd : _) -> NormalForm (pair fst snd) ctx -> LogNormalForm ann fst ctx
-doFst Irrelevant snd t = pure Irrel
-doFst Relevant snd (Ntrl t) = pure (Ntrl $ Fst snd t)
-doFst Relevant snd (Cnstr (Pair (Set _) s' prf t u)) = pure t
-doFst Relevant snd (Cnstr t) = inScope "wrong constructor for fst" $ fatal t
+doFst : (firstRel, secondRel : _) ->
+ (arg : NormalForm (pair firstRel secondRel) ctx) ->
+ LogNormalForm ann firstRel ctx
+
+doFst Irrelevant secondRel arg = pure Irrel
+doFst Relevant secondRel (Ntrl arg) = pure $ Ntrl $ First {secondRel, arg}
+doFst Relevant secondRel (Cnstr (Pair {indexRel = Relevant, elementRel, prf, first, second})) =
+ pure first
+doFst Relevant secondRel (Cnstr t) = inScope "wrong constructor for fst" $ fatal t
export
-doSnd : (fst, snd : _) -> NormalForm (pair fst snd) ctx -> LogNormalForm ann snd ctx
-doSnd fst Irrelevant t = pure Irrel
-doSnd fst Relevant t =
- let t' : NormalForm Relevant ctx
- t' = rewrite sym $ pairRelevantRight fst in t
- in case t' of
- Ntrl t => pure (Ntrl $ Snd fst t)
- Cnstr (Pair _ (Set _) prf t u) => pure u
+doSnd : (firstRel, secondRel : _) ->
+ (arg : NormalForm (pair firstRel secondRel) ctx) ->
+ LogNormalForm ann secondRel ctx
+
+doSnd firstRel Irrelevant arg = pure Irrel
+doSnd firstRel Relevant arg =
+ let arg' : NormalForm Relevant ctx
+ arg' = rewrite sym $ pairRelevantRight firstRel in arg
+ in case arg' of
+ Ntrl arg => pure $ Ntrl $ Second {firstRel, arg}
+ Cnstr (Pair {indexRel, elementRel = Relevant, prf, first, second}) => pure second
Cnstr t => inScope "wrong constructor for snd" $ fatal t
export
-doIf : {r : _} ->
- NormalForm Relevant ctx ->
- NormalForm r ctx ->
- NormalForm r ctx ->
- LogNormalForm ann r ctx
-doIf {r = Irrelevant} t u v = pure Irrel
-doIf {r = Relevant} (Ntrl t) u v = pure (Ntrl $ If t u v)
-doIf {r = Relevant} (Cnstr True) u v = pure u
-doIf {r = Relevant} (Cnstr False) u v = pure v
-doIf {r = Relevant} (Cnstr t) u v = inScope "wrong constructor for case" $ fatal t
+doIf : {rel : _} ->
+ (discriminant : NormalForm Relevant ctx) ->
+ (true, false : NormalForm rel ctx) ->
+ LogNormalForm ann rel ctx
+doIf {rel = Irrelevant} discriminant true false = pure Irrel
+doIf {rel = Relevant} (Ntrl discriminant) true false = pure $ Ntrl $ If {discriminant, true, false}
+doIf {rel = Relevant} (Cnstr True) true false = pure true
+doIf {rel = Relevant} (Cnstr False) true false = pure false
+doIf {rel = Relevant} (Cnstr t) true false = inScope "wrong constructor for if" $ fatal t
export
-doAbsurd : (r : _) -> NormalForm r ctx
+doAbsurd : (rel : _) -> NormalForm rel ctx
doAbsurd Irrelevant = Irrel
doAbsurd Relevant = Ntrl Absurd
export
-doCast : (r : _) -> (a, b : TypeNormalForm ctx) -> NormalForm r ctx -> LogNormalForm ann r ctx
+doCast : (rel : _) ->
+ (oldType, newType : TypeNormalForm ctx) ->
+ (value : NormalForm rel ctx) ->
+ LogNormalForm ann rel ctx
-doCastR : (a : Constructor ctx) ->
- (b : TypeNormalForm ctx) ->
- NormalForm Relevant ctx ->
+doCastHelper : (oldType, newType : Constructor ctx) ->
+ (value : NormalForm Relevant ctx) ->
LogNormalForm ann Relevant ctx
-doCastR a (Ntrl b) t = pure (Ntrl $ CastR a b t)
-doCastR (Universe _) (Cnstr (Universe _)) t = pure t
-doCastR ty@(Pi s s'@(Set _) var a b) (Cnstr ty'@(Pi l l' _ a' b')) t =
- let y : NormalForm (relevance s) (relevance s :: ctx)
- y = point (var, (s ** Refl)) Here
+doCastHelper (Universe {s}) (Universe {s = s'}) value = pure value
+doCastHelper
+ oldType@(Pi {domainSort, codomainSort, domain, codomain})
+ newType@(Pi
+ { domainSort = domainSort'
+ , codomainSort = codomainSort'
+ , domain = domain'
+ , codomain = codomain'
+ })
+ value =
+ let y : NormalForm (relevance domainSort) (relevance domainSort :: ctx)
+ y = point domain.var Here
in do
- let Yes Refl = decEq (s, s') (l, l')
- | No _ => pure (Ntrl $ CastStuck ty ty' t)
- x <- assert_total (doCast (relevance s) (weaken [relevance s] a') (weaken [relevance s] a) y)
- b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure x) (Right . There)))
- b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure y) (Right . There)))
- t <- assert_total (doApp (Sorted.weaken [relevance s] t) x)
- t <- assert_total (doCast Relevant b b' t)
- pure (Cnstr $ Lambda s var t)
-doCastR ty@(Sigma s@(Set k) s' var a b) (Cnstr ty'@(Sigma l l' _ a' b')) t = do
- let Yes Refl = decEq (s, s') (l, l')
- | No _ => pure (Ntrl $ CastStuck ty ty' t)
- t1 <- doFst Relevant (relevance s') t
- u1 <- assert_total (doCast Relevant a a' t)
- b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure t1) Right))
- b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure u1) Right))
- t2 <- doSnd Relevant (relevance s') t
- u2 <- assert_total (doCast (relevance s') b b' t2)
- pure (Cnstr $ Pair (Set k) s' Set u1 u2)
-doCastR ty@(Sigma Prop s'@(Set k) var a b) (Cnstr ty'@(Sigma Prop l' _ a' b')) t = do
- let Yes Refl = decEq s' l'
- | No _ => pure (Ntrl $ CastStuck ty ty' t)
- b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure Irrel) Right))
- b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure Irrel) Right))
- t2 <- doSnd Irrelevant Relevant t
- u2 <- assert_total (doCast Relevant b b' t2)
- pure (Cnstr $ Pair Prop (Set k) Set Irrel u2)
-doCastR Bool (Cnstr Bool) t = pure t
-doCastR a (Cnstr b) t = pure (Ntrl $ CastStuck a b t)
-
-doCast Irrelevant a b t = pure Irrel
-doCast Relevant (Ntrl a) b t = pure (Ntrl $ CastL a b t)
-doCast Relevant (Cnstr a) b t = doCastR a b t
+
+ let Yes Refl = decEq (domainSort, codomainSort) (domainSort', codomainSort')
+ | No _ => pure $ Ntrl $ CastStuck {oldType, newType, value}
+
+ let domainType = weaken [relevance domainSort] domain.type
+ let domainType' = weaken [relevance domainSort] domain'.type
+
+ x <- doCast
+ { rel = relevance domainSort
+ , oldType = assert_smaller oldType domainType'
+ , newType = assert_smaller newType domainType
+ , value = y
+ }
+
+ codomainType <- map1 x codomain
+ codomainType' <- map1 y codomain'
+
+ call <- doApp (weaken [relevance domainSort] value) x
+ body <- doCast
+ { rel = Relevant
+ , oldType = assert_smaller oldType codomainType
+ , newType = assert_smaller newType codomainType'
+ , value = call
+ }
+
+ pure $ Cnstr $ Lambda {domainRel = relevance domainSort, var = Nothing, body}
+doCastHelper
+ oldType@(Sigma {indexSort = indexSort@(Set k), elementSort, index, element})
+ newType@(Sigma
+ { indexSort = indexSort'
+ , elementSort = elementSort'
+ , index = index'
+ , element = element'
+ })
+ value = do
+ let Yes Refl = decEq (indexSort, elementSort) (indexSort', elementSort')
+ | No _ => pure $ Ntrl $ CastStuck {oldType, newType, value}
+
+ first <- doFst Relevant (relevance elementSort) value
+ second <- doSnd Relevant (relevance elementSort) value
+
+ first' <- doCast
+ { rel = Relevant
+ , oldType = assert_smaller oldType index.type
+ , newType = assert_smaller newType index'.type
+ , value = first
+ }
+
+ elementType <- subst1 first element
+ elementType' <- subst1 first' element'
+
+ second' <- doCast
+ { rel = relevance elementSort
+ , oldType = assert_smaller oldType elementType
+ , newType = assert_smaller newType elementType'
+ , value = second
+ }
+
+ pure $ Cnstr $ Pair
+ { indexRel = Relevant
+ , elementRel = relevance elementSort
+ , prf = Relevant
+ , first = first'
+ , second = second'
+ }
+doCastHelper
+ oldType@(Sigma {indexSort = Prop, elementSort = elementSort@(Set k), index, element})
+ newType@(Sigma
+ { indexSort = Prop
+ , elementSort = elementSort'
+ , index = index'
+ , element = element'
+ })
+ value = do
+ let Yes Refl = decEq elementSort elementSort'
+ | No _ => pure $ Ntrl $ CastStuck {oldType, newType, value}
+
+ first <- doFst Irrelevant Relevant value
+ second <- doSnd Irrelevant Relevant value
+
+ first' <- doCast
+ { rel = Irrelevant
+ , oldType = assert_smaller oldType index.type
+ , newType = assert_smaller newType index'.type
+ , value = first
+ }
+
+ elementType <- subst1 first element
+ elementType' <- subst1 first' element'
+
+ second' <- doCast
+ { rel = Relevant
+ , oldType = assert_smaller oldType elementType
+ , newType = assert_smaller newType elementType'
+ , value = second
+ }
+
+ pure $ Cnstr $ Pair
+ { indexRel = Irrelevant
+ , elementRel = Relevant
+ , prf = Relevant
+ , first = first'
+ , second = second'
+ }
+doCastHelper Bool Bool value = pure value
+doCastHelper oldType newType value = pure $ Ntrl $ CastStuck {oldType, newType, value}
+
+doCast Irrelevant oldType newType value = pure Irrel
+doCast Relevant (Ntrl oldType) newType value = pure $ Ntrl $ CastL {oldType, newType, value}
+doCast Relevant (Cnstr oldType) (Ntrl newType) value =
+ pure $ Ntrl $ CastR {oldType, newType, value}
+doCast Relevant (Cnstr oldType) (Cnstr newType) value = doCastHelper oldType newType value
export
-doEqual : (r : _) ->
- (a : TypeNormalForm ctx) ->
- NormalForm r ctx ->
- NormalForm r ctx ->
+doEqual : (rel : _) ->
+ (type : TypeNormalForm ctx) ->
+ (left, right : NormalForm rel ctx) ->
LogNormalForm ann Relevant ctx
--- Relies heavily on typing
-doEqualR : (a : Constructor ctx) -> (b : TypeNormalForm ctx) -> LogNormalForm ann Relevant ctx
-doEqualR a (Ntrl b) = pure (Ntrl $ EqualR a b)
-doEqualR (Universe _) (Cnstr (Universe s)) = pure (Cnstr Top)
-doEqualR ty@(Pi s s' var a b) (Cnstr ty'@(Pi l l' _ a' b')) =
- let u : NormalForm (relevance s) (relevance s :: ctx)
- u = point (var, (s ** Refl)) Here
+equalHelper : (left, right : Constructor ctx) -> LogNormalForm ann Relevant ctx
+equalHelper (Universe {s}) (Universe {s = s'}) = pure (Cnstr Top)
+equalHelper
+ left@(Pi {domainSort, codomainSort, domain, codomain})
+ right@(Pi
+ { domainSort = domainSort'
+ , codomainSort = codomainSort'
+ , domain = domain'
+ , codomain = codomain'
+ }) =
+ let y : NormalForm (relevance domainSort) (relevance domainSort :: Irrelevant :: ctx)
+ y = point domain.var Here
in do
- let Yes Refl = decEq (s, s') (l, l')
- | No _ => pure (Ntrl $ EqualStuck ty ty')
- eq1 <- assert_total (doEqual Relevant (cast s) a' a)
- t <- doCast (relevance s) (weaken [relevance s] a') (weaken [relevance s] a) u
- b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure t) (Right . There)))
- b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure u) (Right . There)))
- eq2 <- assert_total (doEqual Relevant (cast s') b b')
- pure (Cnstr $ Sigma Prop Prop "_" eq1 (Cnstr $ Unsorted.weaken [Irrelevant] $ Pi s Prop var a eq2))
-doEqualR ty@(Sigma s s' var a b) (Cnstr ty'@(Sigma l l' _ a' b')) =
- let t : NormalForm (relevance s) (relevance s :: ctx)
- t = point (var, (s ** Refl)) Here
+
+ let Yes Refl = decEq (domainSort, codomainSort) (domainSort', codomainSort')
+ | No _ => pure $ Ntrl $ EqualStuck {left, right}
+
+ domainEqual <- doEqual
+ { rel = Relevant
+ , type = cast domainSort
+ , left = assert_smaller right domain'.type
+ , right = assert_smaller left domain.type
+ }
+
+ let domainType = Sorted.weaken [relevance domainSort, Irrelevant] domain.type
+ let domainType' = Sorted.weaken [relevance domainSort, Irrelevant] domain'.type
+
+ x <- doCast
+ { rel = relevance domainSort
+ , oldType = domainType'
+ , newType = domainType
+ , value = y
+ }
+
+ codomainType <- map1 x (rename codomain (add Elem Here (There . There)))
+ codomainType' <- map1 y (rename codomain' (add Elem Here (There . There)))
+
+ codomainEqual <- doEqual
+ { rel = Relevant
+ , type = cast codomainSort
+ , left = assert_smaller left codomainType
+ , right = assert_smaller right codomainType'
+ }
+
+ let returnElement = Cnstr $ Pi
+ { domainSort = domainSort
+ , codomainSort = Prop
+ , domain = MkDecl Nothing (Sorted.weaken [Irrelevant] domain.type)
+ , codomain = codomainEqual
+ }
+
+ pure $ Cnstr $ Sigma
+ { indexSort = Prop
+ , elementSort = Prop
+ , index = MkDecl Nothing domainEqual
+ , element = returnElement
+ }
+equalHelper
+ left@(Sigma {indexSort, elementSort, index, element})
+ right@(Sigma
+ { indexSort = indexSort'
+ , elementSort = elementSort'
+ , index = index'
+ , element = element'
+ }) =
+ let x : NormalForm (relevance indexSort) (relevance indexSort :: Irrelevant :: ctx)
+ x = point index.var Here
in do
- let Yes Refl = decEq (s, s') (l, l')
- | No _ => pure (Ntrl $ EqualStuck ty ty')
- eq1 <- assert_total (doEqual Relevant (cast s) a a')
- u <- doCast (relevance s) (weaken [relevance s] a) (weaken [relevance s] a') t
- b <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure t) (Right . There)))
- b' <- assert_total (subst' b' (add (LogNormalForm' ann) (Left $ pure u) (Right . There)))
- eq2 <- assert_total (doEqual Relevant (cast s') b b')
- pure (Cnstr $ Sigma Prop Prop "_" eq1 (Cnstr $ Unsorted.weaken [Irrelevant] $ Pi s Prop var a eq2))
-doEqualR Bool (Cnstr Bool) = pure (Cnstr Top)
-doEqualR Top (Cnstr Top) = pure (Cnstr Top)
-doEqualR Bottom (Cnstr Bottom) = pure (Cnstr Top)
-doEqualR a (Cnstr b) = pure (Ntrl $ EqualStuck a b)
-export
-doEqualSet : (a, b : TypeNormalForm ctx) -> LogNormalForm ann Relevant ctx
-doEqualSet (Ntrl a) b = pure (Ntrl $ EqualL a b)
-doEqualSet (Cnstr a) b = doEqualR a b
-
-doEqual Irrelevant a t u = pure (Cnstr Top)
-doEqual Relevant (Ntrl a) t u = pure (Ntrl $ Equal a t u)
-doEqual Relevant (Cnstr (Universe Prop)) t u = do
- pure (Cnstr $ Sigma Prop Prop ""
- (Cnstr $ Pi Prop Prop "" t (Sorted.weaken [Irrelevant] u))
- (Cnstr $ Unsorted.weaken [Irrelevant] $ Pi Prop Prop "" u (Sorted.weaken [Irrelevant] t)))
-doEqual Relevant (Cnstr (Universe (Set _))) t u = doEqualSet t u
-doEqual Relevant (Cnstr (Pi s (Set k) var a b)) t u =
- let x : NormalForm (relevance s) (relevance s :: ctx)
- x = point (var, (s ** Refl)) Here
+ let Yes Refl = decEq (indexSort, elementSort) (indexSort', elementSort')
+ | No _ => pure $ Ntrl $ EqualStuck {left, right}
+
+ indexEqual <- doEqual
+ { rel = Relevant
+ , type = cast indexSort
+ , left = assert_smaller left index.type
+ , right = assert_smaller right index'.type
+ }
+
+ let indexType = Sorted.weaken [relevance indexSort, Irrelevant] index.type
+ let indexType' = Sorted.weaken [relevance indexSort, Irrelevant] index'.type
+
+ y <- doCast
+ { rel = relevance indexSort
+ , oldType = indexType
+ , newType = indexType'
+ , value = x
+ }
+
+ elementType <- map1 x (rename element (add Elem Here (There . There)))
+ elementType' <- map1 y (rename element' (add Elem Here (There . There)))
+
+ elementEqual <- doEqual
+ { rel = Relevant
+ , type = cast elementSort
+ , left = assert_smaller left elementType
+ , right = assert_smaller right elementType'
+ }
+
+ let returnElement = Cnstr $ Pi
+ { domainSort = indexSort
+ , codomainSort = Prop
+ , domain = MkDecl Nothing (Sorted.weaken [Irrelevant] index.type)
+ , codomain = elementEqual
+ }
+
+ pure $ Cnstr $ Sigma
+ { indexSort = Prop
+ , elementSort = Prop
+ , index = MkDecl Nothing indexEqual
+ , element = returnElement
+ }
+equalHelper Bool Bool = pure (Cnstr Top)
+equalHelper left right = pure $ Ntrl $ EqualStuck {left, right}
+
+doEqualType : (left, right : TypeNormalForm ctx) -> LogNormalForm ann Relevant ctx
+doEqualType (Ntrl left) right = pure $ Ntrl $ EqualL {left, right}
+doEqualType (Cnstr left) (Ntrl right) = pure $ Ntrl $ EqualR {left, right}
+doEqualType (Cnstr left) (Cnstr right) = equalHelper left right
+
+doEqual Irrelevant type left right = pure $ Cnstr Top
+doEqual Relevant (Ntrl type) left right = pure $ Ntrl $ Equal {type, left, right}
+doEqual Relevant (Cnstr (Universe {s = Prop})) left right = do
+ let leftToRight = Cnstr $ Pi
+ { domainSort = Prop
+ , codomainSort = Prop
+ , domain = MkDecl Nothing left
+ , codomain = weaken [Irrelevant] right
+ }
+ let rightToLeft = Cnstr $ Pi
+ { domainSort = Prop
+ , codomainSort = Prop
+ , domain = MkDecl Nothing right
+ , codomain = weaken [Irrelevant] left
+ }
+ pure $ Cnstr $ Sigma
+ { indexSort = Prop
+ , elementSort = Prop
+ , index = MkDecl Nothing leftToRight
+ , element = Sorted.weaken [Irrelevant] rightToLeft
+ }
+doEqual Relevant (Cnstr (Universe {s = Set _})) left right = doEqualType left right
+doEqual Relevant (Cnstr (Pi {domainSort, codomainSort, domain, codomain})) left right =
+ let var : NormalForm (relevance domainSort) (relevance domainSort :: ctx)
+ var = point domain.var Here
in do
- t <- assert_total (doApp (weaken [relevance s] t) x)
- u <- assert_total (doApp (weaken [relevance s] u) x)
- eq <- doEqual Relevant b t u
- pure (Cnstr $ Pi s Prop var a eq)
-doEqual Relevant (Cnstr (Sigma s@(Set _) s' var a b)) t u = do
- t1 <- doFst Relevant (relevance s') t
- u1 <- doFst Relevant (relevance s') u
- t2 <- doSnd Relevant (relevance s') t
- u2 <- doSnd Relevant (relevance s') u
- eq1 <- doEqual Relevant a t1 u1
- bt1 <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure t1) Right))
- bu1 <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure u1) Right))
- t2' <- doCast (relevance s') bt1 bu1 t2
- eq2 <- doEqual (relevance s') (assert_smaller b bu1) t2' u2
- pure (Cnstr $ Sigma Prop Prop "_" eq1 (Sorted.weaken [Irrelevant] eq2))
-doEqual Relevant (Cnstr (Sigma Prop (Set k) var a b)) t u = do
- t2 <- doSnd Irrelevant Relevant t
- u2 <- doSnd Irrelevant Relevant u
- bt1 <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure $ Irrel) Right))
- bu1 <- assert_total (subst' b (add (LogNormalForm' ann) (Left $ pure $ Irrel) Right))
- t2' <- doCast Relevant bt1 bu1 t2
- eq2 <- doEqual Relevant (assert_smaller b bu1) t2' u2
- pure (Cnstr $ Sigma Prop Prop "_" (Cnstr Top) (Sorted.weaken [Irrelevant] eq2))
-doEqual Relevant (Cnstr Bool) t u = do
- relevant <- doIf u (Cnstr Top) (Cnstr Bottom)
- irrelevant <- doIf u (Cnstr Bottom) (Cnstr Top)
- doIf t relevant irrelevant
-doEqual Relevant (Cnstr a) t u = inScope "wrong constructor for equal" $ fatal a
+
+ leftApp <- doApp (weaken [relevance domainSort] left) var
+ rightApp <- doApp (weaken [relevance domainSort] right) var
+
+ equality <- doEqual
+ { rel = Relevant
+ , type = codomain
+ , left = assert_smaller left leftApp
+ , right = assert_smaller right rightApp
+ }
+
+ pure $ Cnstr $ Pi {domainSort, codomainSort = Prop, domain, codomain = equality}
+doEqual
+ Relevant
+ (Cnstr (Sigma {indexSort = indexSort@(Set _), elementSort, index, element}))
+ left
+ right = do
+ leftFirst <- doFst Relevant (relevance elementSort) left
+ rightFirst <- doFst Relevant (relevance elementSort) right
+ leftSecond <- doSnd Relevant (relevance elementSort) left
+ rightSecond <- doSnd Relevant (relevance elementSort) right
+
+ leftEquality <- doEqual
+ { rel = Relevant
+ , type = index.type
+ , left = assert_smaller left leftFirst
+ , right = assert_smaller right rightFirst
+ }
+
+ leftElementType <- subst1 leftFirst element
+ rightElementType <- subst1 rightFirst element
+
+ leftSecond <- doCast (relevance elementSort) leftElementType rightElementType leftSecond
+
+ rightEquality <- doEqual
+ { rel = relevance elementSort
+ , type = rightElementType
+ , left = assert_smaller left leftSecond
+ , right = assert_smaller right rightSecond
+ }
+
+ pure $ Cnstr $ Sigma
+ { indexSort = Prop
+ , elementSort = Prop
+ , index = MkDecl Nothing leftEquality
+ , element = Sorted.weaken [Irrelevant] rightEquality
+ }
+doEqual
+ Relevant
+ (Cnstr (Sigma {indexSort = Prop, elementSort = elementSort@(Set _), index, element}))
+ left
+ right = do
+ leftFirst <- doFst Irrelevant Relevant left
+ rightFirst <- doFst Irrelevant Relevant right
+ leftSecond <- doSnd Irrelevant Relevant left
+ rightSecond <- doSnd Irrelevant Relevant right
+
+ leftEquality <- doEqual
+ { rel = Irrelevant
+ , type = index.type
+ , left = assert_smaller left leftFirst
+ , right = assert_smaller right rightFirst
+ }
+
+ leftElementType <- subst1 leftFirst element
+ rightElementType <- subst1 rightFirst element
+
+ leftSecond <- doCast Relevant leftElementType rightElementType leftSecond
+
+ rightEquality <- doEqual
+ { rel = Relevant
+ , type = rightElementType
+ , left = assert_smaller left leftSecond
+ , right = assert_smaller right rightSecond
+ }
+
+ pure $ Cnstr $ Sigma
+ { indexSort = Prop
+ , elementSort = Prop
+ , index = MkDecl Nothing leftEquality
+ , element = Sorted.weaken [Irrelevant] rightEquality
+ }
+doEqual Relevant (Cnstr Bool) left right = do
+ whenLeftTrue <- doIf right (Cnstr Top) (Cnstr Bottom)
+ whenLeftFalse <- doIf right (Cnstr Bottom) (Cnstr Top)
+ doIf left whenLeftTrue whenLeftFalse
+doEqual Relevant (Cnstr t) left right = inScope "wrong constructor for equal" $ fatal t
+
+substDecl : DeclForm ~|> Hom (LogNormalForm' ann) (LogDeclForm ann)
+substDecl (MkDecl var type) f = pure (MkDecl var !(subst' type f))
substCnstr : Constructor ~|> Hom (LogNormalForm' ann) (LogConstructor ann)
-substCnstr (Universe s) f = pure (Universe s)
-substCnstr (Pi s s' var a b) f = do
- a <- subst' a f
- b <- subst' b (lift [(_ ** (var, (s ** Refl)))] f)
- pure (Pi s s' var a b)
-substCnstr (Lambda s var t) f = do
- t <- subst' t (lift [(_ ** (var, (s ** Refl)))] f)
- pure (Lambda s var t)
-substCnstr (Sigma s s' var a b) f = do
- a <- subst' a f
- b <- subst' b (lift [(_ ** (var, (s ** Refl)))] f)
- pure (Sigma s s' var a b)
-substCnstr (Pair s s' prf t u) f = do
- t <- subst' t f
- u <- subst' u f
- pure (Pair s s' prf t u)
+substCnstr (Universe {s}) f = pure (Universe {s})
+substCnstr (Pi {domainSort, codomainSort, domain, codomain}) f = do
+ domain <- substDecl domain f
+ codomain <- subst' codomain (lift [(_ ** domain.var)] f)
+ pure (Pi {domainSort, codomainSort, domain, codomain})
+substCnstr (Lambda {domainRel, var, body}) f = do
+ body <- subst' body (lift [(_ ** var)] f)
+ pure (Lambda {domainRel, var, body})
+substCnstr (Sigma {indexSort, elementSort, index, element}) f = do
+ index <- substDecl index f
+ element <- subst' element (lift [(_ ** index.var)] f)
+ pure (Sigma {indexSort, elementSort, index, element})
+substCnstr (Pair {indexRel, elementRel, prf, first, second}) f = do
+ first <- subst' first f
+ second <- subst' second f
+ pure (Pair {indexRel, elementRel, prf, first, second})
substCnstr Bool f = pure Bool
substCnstr True f = pure True
substCnstr False f = pure False
@@ -245,57 +514,58 @@ substCnstr Top f = pure Top
substCnstr Bottom f = pure Bottom
substNtrl : Neutral ~|> Hom (LogNormalForm' ann) (LogNormalForm ann Relevant)
-substNtrl (Var var sort prf i) f = case f i of
+substNtrl (Var {var, i}) f = case f i of
Left t => t
- Right j => pure (Ntrl $ Var var sort prf j)
-substNtrl (App r t u) f = do
- t <- substNtrl t f
- u <- subst' u f
- assert_total (doApp t u)
-substNtrl (Fst r t) f = do
- t <- substNtrl t f
- doFst Relevant r t
-substNtrl (Snd r t) f = do
- t <- substNtrl t f
- doSnd r Relevant $ rewrite pairRelevantRight r in t
-substNtrl (If t u v) f = do
- t <- substNtrl t f
- u <- subst' u f
- v <- subst' v f
- doIf t u v
+ Right i => pure $ Ntrl $ Var {var, i}
+substNtrl (App {argRel, fun, arg}) f = do
+ fun <- substNtrl fun f
+ arg <- subst' arg f
+ assert_total (doApp fun arg)
+substNtrl (First {secondRel, arg}) f = do
+ arg <- substNtrl arg f
+ doFst Relevant secondRel arg
+substNtrl (Second {firstRel, arg}) f = do
+ arg <- substNtrl arg f
+ let arg = rewrite pairRelevantRight firstRel in arg
+ doSnd firstRel Relevant arg
+substNtrl (If {discriminant, true, false}) f = do
+ discriminant <- substNtrl discriminant f
+ true <- subst' true f
+ false <- subst' false f
+ doIf discriminant true false
substNtrl Absurd f = pure (doAbsurd Relevant)
-substNtrl (Equal a t u) f = do
- a <- substNtrl a f
- t <- subst' t f
- u <- subst' u f
- doEqual _ a t u
-substNtrl (EqualL a b) f = do
- a <- substNtrl a f
- b <- subst' b f
- doEqualSet a b
-substNtrl (EqualR a b) f = do
- a <- substCnstr a f
- b <- substNtrl b f
- doEqualR a b
-substNtrl (EqualStuck a b) f = do
- a <- substCnstr a f
- b <- substCnstr b f
- pure (Ntrl $ EqualStuck a b)
-substNtrl (CastL a b t) f = do
- a <- substNtrl a f
- b <- subst' b f
- t <- subst' t f
- doCast _ a b t
-substNtrl (CastR a b t) f = do
- a <- substCnstr a f
- b <- substNtrl b f
- t <- subst' t f
- doCastR a b t
-substNtrl (CastStuck a b t) f = do
- a <- substCnstr a f
- b <- substCnstr b f
- t <- subst' t f
- pure (Ntrl $ CastStuck a b t)
+substNtrl (Equal {type, left, right}) f = do
+ type <- substNtrl type f
+ left <- subst' left f
+ right <- subst' right f
+ assert_total (doEqual Relevant type left right)
+substNtrl (EqualL {left, right}) f = do
+ left <- substNtrl left f
+ right <- subst' right f
+ assert_total (doEqualType left right)
+substNtrl (EqualR {left, right}) f = do
+ left <- substCnstr left f
+ right <- substNtrl right f
+ assert_total (doEqualType (Cnstr left) right)
+substNtrl (EqualStuck {left, right}) f = do
+ left <- substCnstr left f
+ right <- substCnstr right f
+ assert_total (doEqualType (Cnstr left) (Cnstr right))
+substNtrl (CastL {oldType, newType, value}) f = do
+ oldType <- substNtrl oldType f
+ newType <- subst' newType f
+ value <- subst' value f
+ assert_total (doCast Relevant oldType newType value)
+substNtrl (CastR {oldType, newType, value}) f = do
+ oldType <- substCnstr oldType f
+ newType <- substNtrl newType f
+ value <- subst' value f
+ assert_total (doCast Relevant (Cnstr oldType) newType value)
+substNtrl (CastStuck {oldType, newType, value}) f = do
+ oldType <- substCnstr oldType f
+ newType <- substCnstr newType f
+ value <- subst' value f
+ assert_total (doCast Relevant (Cnstr oldType) (Cnstr newType) value)
subst' (Ntrl t) f = substNtrl t f
subst' (Cnstr t) f = pure $ Cnstr !(substCnstr t f)
@@ -304,9 +574,3 @@ subst' Irrel f = pure Irrel
export
subst : NormalForm ~|> Hom (LogNormalForm ann) (LogNormalForm ann)
subst t f = subst' t (Left . f)
-
--- Utilities -------------------------------------------------------------------
-
-export
-subst1 : {s' : _} -> NormalForm s ctx -> NormalForm s' (s :: ctx) -> LogNormalForm ann s' ctx
-subst1 t u = subst' u (add (LogNormalForm' ann) (Left $ pure t) Right)