summaryrefslogtreecommitdiff
path: root/src/Total/Syntax.idr
blob: 6a61cf5e7fc191cbe847e79a4efe358adb0d66cc (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
73
74
75
76
77
78
79
80
81
82
83
module Total.Syntax

import public Data.List
import public Data.List.Quantifiers
import public Data.SnocList
import public Data.SnocList.Quantifiers
import public Total.Term

infixr 20 ~>*
infix 9 .*

public export
(~>*) : SnocList Ty -> Ty -> Ty
tys ~>* ty = foldr (~>) ty tys

public export
data Len : SnocList Ty -> Type where
  Z : Len [<]
  S : Len tys -> Len (tys :< ty)

%name Len k, m, n

public export
0 Fun : Len tys -> (Ty -> Type) -> Type -> Type
Fun Z arg ret = ret
Fun (S {ty} k) arg ret = Fun k arg (arg ty -> ret)

after : (k : Len tys) -> (a -> b) -> Fun k p a -> Fun k p b
after Z f x = f x
after (S k) f x = after k (f .) x

before :
  (k : Len tys) ->
  (forall ty. p ty -> q ty) ->
  Fun k q ret ->
  Fun k p ret
before Z f x = x
before (S k) f x = before k f (after k (. f) x)

export
Lit : Nat -> Term ctx N
Lit 0 = Zero
Lit (S n) = Suc (Lit n)

AbsHelper :
  (k : Len tys) ->
  Fun k (flip Elem (ctx ++ tys)) (Term (ctx ++ tys) ty) ->
  Term ctx (tys ~>* ty)
AbsHelper Z x = x
AbsHelper (S k) x =
  AbsHelper k $
  after k (\f => Term.Abs (f SnocList.Elem.Here)) $
  before k SnocList.Elem.There x

export
Abs' :
  (k : Len tys) ->
  Fun k (Term (ctx ++ tys)) (Term (ctx ++ tys) ty) ->
  Term ctx (tys ~>* ty)
Abs' k = AbsHelper k . before k Var

export
App' : {tys : SnocList Ty} -> Term ctx (tys ~>* ty) -> All (Term ctx) tys -> Term ctx ty
App' t [<] = t
App' t (us :< u) = App (App' t us) u

export
(.) : {ty, ty' : Ty} -> Term ctx (ty' ~> ty'') -> Term ctx (ty ~> ty') -> Term ctx (ty ~> ty'')
t . u = Abs' (S Z) (\x => App (wkn t (Drop Id)) (App (wkn u (Drop Id)) x))

export
(.*) :
  {ty : Ty} ->
  {tys : SnocList Ty} ->
  Term ctx (ty ~> ty') ->
  Term ctx (tys ~>* ty) ->
  Term ctx (tys ~>* ty')
(.*) {tys = [<]} t u = App t u
(.*) {tys = tys :< ty''} t u = Abs' (S Z) (\f => wkn t (Drop Id) . f) .*  u

export
lift : {ctx : SnocList Ty} -> Term [<] ty -> Term ctx ty
lift t = wkn t (empty ctx)