summaryrefslogtreecommitdiff
path: root/src/Level0.idr
blob: bccaa4f59237691604975e1e4d6deac31a4f49b0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
module Level0

import Data.SnocList.Elem
import NormalForm
import Term
import Thinning

Res : Type -> Type
Res = Pair ()

public export
data NormSubst : SnocList Ty -> SnocList Ty -> Type where
  Base : ctx' `Thins` ctx -> NormSubst ctx ctx'
  (:<) : NormSubst ctx ctx' -> Normal ctx ty -> NormSubst ctx (ctx' :< ty)

%name NormSubst sub

shift : NormSubst ctx ctx' -> NormSubst (ctx :< ty) ctx'
shift (Base thin) = Base (Drop thin)
shift (sub :< t) = shift sub :< wknNorm t (Drop Id)

lift : NormSubst ctx ctx' -> NormSubst (ctx :< ty) (ctx' :< ty)
lift (Base thin) = Base (keep thin)
lift (sub :< t) = shift (sub :< t) :< Ntrl (Var Here)

index : NormSubst ctx' ctx -> Elem ty ctx -> Normal ctx' ty
index (Base thin) i = Ntrl (Var $ index thin i)
index (sub :< t) Here = t
index (sub :< t) (There i) = index sub i

restrict : NormSubst ctx1 ctx2 -> ctx3 `Thins` ctx2 -> NormSubst ctx1 ctx3
restrict (Base thin') thin = Base (thin' . thin)
restrict (sub :< t) Id = sub :< t
restrict (sub :< t) (Drop thin) = restrict sub thin
restrict (sub :< t) (Keep thin) = restrict sub thin :< t

-- Evaluates a term in a context of normal forms.
partial
eval : Term ctx ty -> NormSubst ctx' ctx -> Res (Normal ctx' ty)
partial
evalSub : Subst ctx ctx'' -> NormSubst ctx' ctx -> Res (NormSubst ctx' ctx'')
partial
rec : Normal ctx N -> Normal ctx ty -> Normal (ctx :< ty) ty -> Res (Normal ctx ty)

eval (Var i) sub = pure (index sub i)
eval (Abs t) sub = [| Abs (eval t $ lift sub) |]
eval (App t u) sub = do
  t <- eval t sub
  case t of
    Abs t => do
      u <- eval u sub
      eval (forgetNorm t) (Base Id :< u)
    Ntrl t => Ntrl <$> App t <$> eval u sub
eval Zero sub = pure Zero
eval (Succ t) sub = [| Succ (eval t sub) |]
eval (Rec t u v) sub = do
  t <- eval t sub
  u <- eval u sub
  v <- eval v (lift sub)
  rec t u v
eval (Sub t sub') sub = do
  sub' <- evalSub sub' sub
  eval t sub'

evalSub (Base thin) sub' = pure (restrict sub' thin)
evalSub (sub :< t) sub' = [| evalSub sub sub' :< eval t sub' |]

rec Zero u v = pure u
rec (Succ t) u v = do
  val <- rec t u v
  eval (forgetNorm v) (Base Id :< val)
rec (Ntrl t) u v = pure (Ntrl $ Rec t u v)