Skip to content

Instantly share code, notes, and snippets.

@EduardoRFS
Last active April 6, 2024 18:50
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EduardoRFS/c549a792e1e167bb1638d4780f35221a to your computer and use it in GitHub Desktop.
Save EduardoRFS/c549a792e1e167bb1638d4780f35221a to your computer and use it in GitHub Desktop.

Examples

[@import stdlib.http.v1];

(x => y => (x_plus_y: x + y) => );

((A, x))
(f: () -> (A: *, x: A)) =>
  (A, x) = (f ());
  A;

id = (A: *) => (x: A) => x;
id = id (*) Int;
X = Int -> Int;

id: (A: *) -> A -> A = x => x;

X: * = 1;

pure: (M: * -> *) -> (A: *) -> (A -> M A) -> A -> M A;


Show = {
  T: *;
  show: T -> String;
};
show: {S: Show} -> S.T -> String;

M: {
  T: *;
} = {
  T = Int;
}

T A = T A
T A = T B

* -> *

X = (A: *) -> A;
M = {
  T: *;
};

F = (M: { X = * }) => ();

F = (M: { T: *; x: T; show: T -> String; }) => M.show M.x;
F = ({ T: *; x: T; show: T -> String; }) -> String;

F = (M: { T: *; show: T -> String; }) => (x: M.T) => M.show x;
F = (M: { T: *; show: T -> String; }) -> M.T -> String;

F = (X: { T: * }) => X;

Pair {A} = (A, A);

id = x => x;
T = Int -> Int;


x = true;
y = x | true -> 1 | false -> 0;

User = {
  id: Nat;
  name: String;
};

eduardo = {
  id = 0;
  name = "Eduardo";
};

Monad = {
  T: * -> *;
  pure: {A} -> A -> T A;
};

id: (A: *) -> A -> A;
m: (A: *) -> A -> { X: * };

id x = x;
rec%map f l =
  l
  | [] -> []
  | el :: tl -> f el :: map f tl;

X = *;
S = { A: * };
M: S = { A = Int };
((M: S) => M) ({ A = Int });

f (M: S) = ();

type_struct_id ({ A }: { A: * }) (x: A) = x;

A = Int;
B = 1;

T: * = Int;

X = {
  A: *;
  B: *;
  X: Unify A A;
};

T = { A: * };
F = (P: { A: _ }) => P.A
m =
  M = { T = Int };
  F M;

M = [%graphql {
  users(id: 0) {
    name
    email
  }
}];

f = [%c {
  x: for (i = 0; i <= 10; i++) {
    print(i);
  };

  if (true) {
    print("a");
  } else {
    print("b");
  };

  goto x;
}];

q = [%sql SELECT * FROM users WHERE name = "Eduardo" WHERE id = 0]

{ a; b; } = { a = 1; b = (); };

X =
  M: { A: *; } = { A = Int; };
  M;
X = ((M: { A: *; }) => M) { A = Int; };
X = ({ A = Int; } : { A: *; });

f = x => x;

f = ?A => A;
?M = {};
x = (a: int) => a;

add: !(x: Int, y: Int) -> Int = (x, y) => x + y;
id: ?A -> A -> A;
id: {A} -> A -> A;

pure: ?(M: Monad) -> ?A -> A -> M A;
pure: {M: Monad} -> {A} -> A -> M A;

add: Int -> Int -> Int;

incr = ?(1 + _);
incr = ?add 1;

F = (A: *) => A;
F = A => A;

M: { T: * } = { T}
F = (X: { T: * }) => X;
S = {
  T: *;
};
M: { A: * } = { A :}

Show = {
  T: *;
  show: T -> String;
};
show {S: Show} (x: S.T) => S.show x;

({A}) = {
  T = Int;
  show x = Int.to_string x;
};

show 1;
show "a";

{M} = {}

User #= {
  id: Nat;
  name: String;
};

Id = (A: *) => A;

map: {A} -> {B} -> (A -> B) -> List A -> List B;
map: {A} -> {B} -> (A ~> B) -> List A ~> List B;

map f l =
  l
  | [] -> []
  | el :: tl -> f el :: map f tl;

get: String -[HTTP]> String;
read_disk file =
  content = perform Read ("/tmp/" ^ file);
  content ^ "x";

read_disk: String -[IO]> String;
id: {A} -> A -> A;

map_read_disk: List Int -[IO]> List Int = map read_disk;
map_id: {A} -> List A -> List A = map id;

f: Int ~> Int;

// TODO: explain why this should be rejected
T = ({ X; A: * })) => X == A;
T = ({ X: *; A = X; })) => X == A;

f = (A: *) => (x: A) => x;
f = ({ A: *; x }) => (x: A);

f = T => (x: T Int) => x;


f: (T: #(Int) -> *) -> T Int -> T Int;

T: #(Int) -> *

f = T => (x: T (Int: *)) => x;
f: (T: * -> *) -> T Int -> T Int;

f = f Option;

expected:
received: {A} -> A -> A;

S = {
  A: _;
  X: *;
};

Id (A: *) = A;

X = Id Int

F (A: *) = A;

App {P} {R} (F: P -> R) (X: P) = F P;
// TODO: universe polymorphism to accept the following
F: (T: * -> *) -> App T Int;
F: (T: * -> *) -> T Int;
F_ (T: * -> *) = F T;
F: (T: #Int -> #String) -> T Int;

T Int = (Return T)[(Param T) := Int];

read_file: String -[ IO ]> String;

Component {Props} = Props -> DOM;

rec%map f l = l | [] -> [] | el :: tl -> map f l;

Option {A} =
  | None
  | Some A;

f x = x | None -> 1 | Some x -> 1;

Option {A} = {
  None: Option {A};
  Some: A -> Option {A};
};

{ None; Some } = Option;




None: {A} -> (| None | Some A);
Some: {A} -> A -> (| None | Some A);

f: (| A | B ) = ;
Option: (A: *) => | None | Some A;

rec%add =
  | (0, y) => y
  | (x, y) => add (x - 1, y + 1);

f =
  | x => 1
  | B => 2
  for

f = a -> a;
T: (A: *) => A = (A: *) => A;

f: (
  Id A = A;
  Id Int
) = 1;

{} = {}

add (a, b) = a + b;
three = add (1, 2);

x = add 1;


@deriving(field)
User = {
  id: Nat;
  name: String;
  banned: Bool;
};

eduardo = { id = 0; name = "Eduardo" };

view_name user = <span>user.name</span>;

view_name user =
  { name; banned; _ } = user;
  name = banned | false -> name | true -> "_" ^ name;
  <span>name</span>;

linear_id {A: &} (x: A) = x;
y = 1;
x = linear_id 1;
State = {
  counter: Int;
};
x = Rc.alloc State { counter = 1; };
x = Rc.free State;
M (state: State): State =
  { counter } = state;
  { counter }

T = {
  X: Option *;
  A: Param X;
};

X: { T: * };
M = X;

Id (A: *) (x: A) = x;
F A B = Id B A;


X: _;
F: (P: { X: X; A: *; }) -> ();

M = {
  T: *;
};

x = (1: Int);
x = ((x: Int) => x);

x: (A: *, A) = (A = Int, x = 1);

{ A; x; y; }: { A: *; x: A; y: A } = { A = Int; x = 1; y = 2; };

a = (a: Nat, b: Nat);

id: (A: *) -> A -> A;
map: {A B} -> (f: A -> B, l: List A) -> List B;
map: (f: 'A -> 'B, l: List 'A) -> List 'B;

sequence1: (A: *) -> A -> (B: *) -> B -> B;
sequence2: (A: *) -> (B: *) -> A -> B -> B;
record1: { A: *; B: *; a: A; b: B; };
record2: { A: *; a: A; B: *; b: B; };

_ -> _ ->

(P => E2) E1;
(P = E1; E2);
F (X: _) (A: *) = assert false

Monad = (
  Monad: * -> *;
  pure: (A: *) -> Monad A;
);

Calculus

Two basic sorts, small type(sT) and type(T), where sT contain all small types that are subject to the FORGET rule that allows to introduce implicit existentials and T are all small types that are not subject to the FORGET rule.

Ideally it should also contain an explicit way to weaken T, such as T[A := *], T[-A] maybe T[A: *].

This should allow the type system to be decidable while polymorphism still works for existential records. And I believe it to be sound as existential records are weak existential records. I'm still a bit concerned if that doesn't break in the presence of dependent products.

A: * means A is a type(T), so (A: *) -> A -> A is identity function and still works for modules.

T => (x: T Int)

(x: &Int) -> (&Int, &Int)

Duplicated

expected :: (forall a. a -> a) -> _b -> ()
received :: forall c. c        -> c  -> ()

expected :: (forall a. a -> a) -> _b -> ()
received :: _c                 -> _c -> ()

received :: (forall a. a -> a) -- _c := (forall a. a -> a)
expected :: _c

f (a: 'A) (b: 'A) = (b : {A} -> A -> A);

Id = {A} -> A -> A;
f: Link Id -> Link Id -> Link Id;

SmolTeika

X = { A: Int; B: Int; C: Int; };

x: X = magic ();
{ A; B; C; } = x;

X = (A: Int, (B: Int, C: Int));
x: X = magic ();
A = fst X;
B = fst (snd X);
C = snd (snd X);

(A: *) -> A;

M: (A: *, (A, A -> String)) = magic ();


M: (A: *, x: A) = (A = Int; x = 1);

U = (A: *, ((A = A, A -> ())) -> ());
V = (A = U, A -> ());

V <= U;
(A = U, A -> ()) <= (A: *, ((A = A, A -> ())) -> ());

(A = U, A -> ()) <= (A: *, ((A = A, A -> ())) -> ());

Int = (#Int: ##Int);

N = (A: *) => A;

N: (A: *, #A) = (A = Int, A);

IdT = (A: *) -> #A;
f (Id: IdT) (x: Id Int) = x;

f (T: * -> *)
Id: (A: *) -> #A = (A: *) => A;
(A: *) -> *

T = (A: *, (_ = A, x: A));

T = (A: *) -> (B = A, _ : A);
x = f (Int -> Int);

T = (A: *) => (B = A, _ = A);`

x = (A = *, A);

(A: *, (x: A, y: A))
(A: *, _: (B: *, (x: A, y: B)));
(A: *, _: (B: *, (x: B, y: A)));
(B: *, _: (A: *, (x: A, y: B)));
(B: *, _: (A: *, (x: B, y: A)));

(A: *, _: (x: A, (B: *, y: B)));
(B: *, _: (x: B, (A: *, y: A)));


(A: *, _: (x: A, (B: *, y: B)));
(A: *, _: (x: A, (B: *, y: B)))

add a b = (
  c = a + b;
  c
);


(x: t = e1; e2);
(((x: t) => e2) (e1));

(e: t);
(((x: t) => x) e);

M = {
  Y: (A: *) = (A = Int, x = one);
};


(A: *, x: A) -> A;
X = P;

m: Fst P = snd X;

(L, m) = P;
x = (m: L);

f = (A: *) => (P: (A = A, x: A)) => P;

// TODO: support this type
(f: (A: *, x: A) -> (A = A, x: A));

(f: (P: (A: *, x: A)) -> (A = Fst P, x: A));
(f: )

Ex = (A: *, x: A);
// works, one: int
one =
  P: Ex = (A = Int, x = one);
  snd P;
one = ((P: Ex) => snd P) (A = Int, x = one);

// fails, type would escape it's scope
fails =
  P: Ex = ((A = Int, x = one): Ex);
  snd P;
fails = ((P: Ex) => snd P) ((A = Int, x = one): Ex);

// fails, type would escape it's scope
fails =
  P: Ex = (A = Int, x = one);
  M = (A = fst P, x = snd P);
  snd M;
fails = ((P: Ex) => snd P) ((A = Int, x = one): Ex);

M: (A: *, x: A) = M;
X = M;
P = X.A;
M: (A = M.A, x: A)

f = (X: Int) => (A: *, x: A);
(f 1).A

f (T: * -> *)
f (A: *) =
  A
  | Nat -> "nat"
  | String -> "string";
f (A: &) =
  A
  | Nat -> "nat"
  | String -> "string";

f: (Car -> ()) -> ();
f ((x: Tesla) => ());


expected :: Car -> ()
received :: Tesla -> ()

received :: Car
expected :: Tesla

expected :: ()
received :: ()


f = (M: (A: *, x: A)) -> M.A;

x = f ((A = Int, x = 1): (A: *, x: A))


(A: Int, x: A).A

_{ A: _; }
x => x.1;

x = (x = 1, y = 2)

User = (
  id: Nat,
  name: String,
);

eduardo = (
  id = 0,
  name = "a"
);

User = {
  id: Nat;
  name: String;
};
eduardo = {
  id = 0;
  name = "a";
};

f = (x: (A: Int; ..._)) => x.A;
z = f (A = 1, x = 2);

a = { (x, y) = (1, 2); };
b = { x: Nat; y: Nat; };

T = Int -> (Int, Int);
x = (Int, Int);

fst: (R: * -> *) -> (P: (L: *, r: R L)) -> P.L;
snd: (R: * -> *) -> (P: (L: *, r: R L)) -> R P.L;

F: Nat -> #Int;

Id: (A: *) -> A -> A;

x = Id ((A: *) -> #A);

// λ→
((x: Int) -> Int): *;
((A: #Int) -> Int): *;
((x: Int) -> #Int): *;

// System λω
((A: *) -> #A): * -> *;
((A: * -> *) -> #T): (* -> *) -> * -> *;
((A: * -> *) -> #(T Int)): (* -> *) -> *;
((A: #Int) -> (A: *) -> #A): _;

// System Fω
((A: *) -> A): *;
((T: * -> *) -> T A): *;
((T: * -> *) -> T): _;

(x: Int, y: Int): *;
(A: #Int, B: #Int): *;

(A: *, x: A): *;
(T: * -> *, x: T Int): *;
((A: *) -> A): *;
((T: * -> *) -> T A): *;

((A: *) -> #A): * -> *;
((T: * -> *) -> #T): (* -> *) -> * -> *;
(A: *, X: #A): (*, *);
(T: * -> *, X: #T): (* -> *, * -> *);

*;
* -> *;

Id = (A: *) => A;
make = (A: *) => (x: A) => (x = A, y = 1);
accept: (M: (X: *, Y: X)) -> M;
(X

p = f ((A: *) -> #A) Id;

p = (x = Id, y = 1);

pair: (A: *, B: A) = (A = Int, B = 1);


m =
  p: (A: *, x: A) = (A = Int, x: Int);
  p;

m = ((p: (A: *, x: A)) => p)
      ((A = Int, x: Int): (A: *, x: A));

x := 1;


T = a == b;
t = 1 === 1;
T: #Int = Int;
x <== e1;
e2
((x => e2) e1)
(x <- e1; e2)


id = (A: *) => (x: A) => x;
id = {A: *} => (x: A) => x;
id = x => x;

Monad = {
  T: * -> *;
  pure: A -> T A
};
pure: {M: Monad} -> {A: *} -> A -> M A;

option_int: Option Int = pure {Option} {Int} 1;

make_array: (x: Int | x >= 0) -> (A: *) -> (initial: A) -> Array A;

twice_one = ((_: gte -1 0) -> (A: *) -> (initial: A) -> Array A) ;


// m.te
// m.tei
// m.test.tei
// m.extend.tei

// untyped
((x => e2) e1) === (e2[x := e1]);
(x = e1; e2) === (e2[x := e1]);

// subtyping
(((x: s) => e2) (e1: t)) =~= (e2[x := e1]);
(x: s = (e1: t); e2) =~= (e2[x := e1]);

(m: t) == (((x: t) => x) m);
(x: t = e1; e2) == (((x: t) => e2) e1);
(x: t = e1; e2) != (x = (e1: t); e2);


F (make_m ());

p = ((A = Int, x = 1) : (A: *, x: A));


Ex = (A: *, x: A);
one =
  P: Ex = (A = Int, x = one);
  snd P;
one = ((P: Ex) => snd P) (A = Int, x = one);


(e : t) === (((x: t) => x) e)

{ x: Nat } <: { x: Nat; y: Nat }

(((x: { x: Nat; }) => x) (_: { x: Nat; y: Nat }))

Program =
  ((magic ()), (magic ()), e2));
Program =
  (User: User_S = magic ();
   Message: Message_S = magic ();
   (User, Message, e2));
Test = ();

e = (x: Int) => x;
x1 = (e: (x: Int) -> Int);
x2 = ((z: (x: Int) -> x) => z) e;

(x := e1; e2)

(x: Nat) => (y: x == 1) => x;

n = 1;
x =
  1 == n
  | Eq => x
  | Neq => y;

Nat = {n} -> Int | n >= 0;

((x: 1) => x) 1;

(x = e1; e2);


S (T: *) = (zero: T; succ: T -> T);
ExM (R: *) (cb: (T: *) -> S T -> R) =
  cb Int (zero = 0; succ = x => x + 1);
M = ExM ();

Id = (A: *) -> (x: A) -> (x: A);
id: (A: *) -> (x: A) -> A = (A: *) => (x: A) => x;
f = (id: (A: *) => (x: A));

Bool = (R: &) => R => R => R;
(true_: Bool) R a b = a;
(false_: Bool) R a b = b;
if_true_x_else_x_concat_y (pred: Bool) (x: String) (y: String) =
  pred String x (x ^ y);

Bool = (I: &) -> (O: &) -> (I -> O) -> (I -> O) -> I -> O;
(true_: Bool) I O x y a = x a;
(false_: Bool) I O x y a = y a;
(not_: Bool -> Bool) b = b Bool Bool (() => false_) (() => true_) ();
(and_: Bool -> Bool -> Bool) l r = l Bool Bool (r => r) (_r => false_) r;
(or_: Bool -> Bool -> Bool) l r = l Bool Bool (_r => true_) (r => r) r;

Bool =

if_true_x_else_x_concat_y (pred: Bool) (x: String) (y: String) =
  pred String String (x => x) (x => x ^ y) x;
if_ (pred: Bool) =>
  (bool: A -> B) =>
  (else_: A -> B) =>

Nat: {
  T: *;
} = {
  T = Int;
};

Id = (L: U) => (A : * : L) => (x: A) => x;

M: {
  T: *;
  x: T;
} = {
  S = {
    name: String;;
  };
  x = {
    name = "Eduardo";
  };
};

f = (P1: (A: *; x: A)) =>
  (A; x) = P1;
  (A; x);
f = (P1: (A: *; (B = A; x: A)) =>
  (A; (B; x)) = P1;
  (A; (B; x));

S: {
  T: _;
  x: T;
} = {
  T = Int;
  x = 1;
}
x: M.T = M.x;

f = (K: ?) => (A: K) => (x: A) => x;
f: (A: *) -> (B: *) -> A -> B = assert false
LAMBDA(
  DUP;
  CALL;
);
DUP;
CALL;

PUSH 1;
PUSH 2;
ADD;

PUSH 1;
LAMBDA(PUSH 2; ADD);
CALL;

1 + 2
(x => x + 2) 1

Hurkens

⊥ = (A: *) -> A;
¬ φ === φ -> ⊥;S === S -> *;
U = (X:) -> (℘℘X -> X) -> ℘℘X;
τ: ℘℘U -> U = (t: ℘℘U) => (X:) => (f : ℘℘X -> X) => (p : ℘X) =>
  t ((x : U) => p (f (x X f)));
σ: U -> ℘℘U = (s: U) => s U τ;
∆ = (y: U) => (p: ℘U) -> σ y p -> p (τ (σ y));: U = τ ((p: ℘U) => (x: U) -> σ x p -> p x);

Opposites

  • positive function, negative args
  • negative function, positive args
// works
pid = (x: -) =[+]> x;
nid = (x: +) =[-]> x;

// works
pnapply = (f: -) =[+]> (x: +) =[-]> f (x: +);
npapply = (f: +) =[-]> (x: -) =[+]> f (x: -);
// rejected
ppapply = (f: -) =[+]> (x: -) =[+]> = f (x: +);
nnapply = (f: +) =[-]> (x: +) =[-]> = f (x: -);

// rejected
fix = f => f f;
apply_fix = f => apply f f;
id_fix = f => id f f;

pnfix = (x: -) =[+]> (y: +) =[-]> x y;
npfix = (x: +) =[-]> (y: -) =[+]> x y;

pfix = (f: -) =[+]> f (f: +);
nfix = (f: +) =[-]> f (f: -);

pflip: - -[+]> + = ?;
nflip: + -[-]> - = ?;

fix = f => f(f);
fix(fix)

id: (K:) -> (A: K) -> (x: A) -> A =
  (K:) => (A: K) => (x: A) => x;

Polar Types

All types have polarity and no restriction on elimination, just on construction.

Polar Arrows

If arrows themselves have polarity, what is the relationship between the parameter and the return with the function?

Cases to study

Description Conclusion
p. x -[p]> p Polarity is meaningless
p. p -[p]> x Polarity is meaningless
p. x -[p]> -p ?: fix can be described
p. p -[p]> -p ?: fix can be described
p. -p -[p]> x ?: lazy fix still works
p. -p -[p]> p Empty, no id or apply
p. -p -[p]> -p ?
Nat = (R: -p) =[p]> R =[p]> (Nat =[-p]> R) =[p]> R;
Self = R =[p]> Self =[p]> R


// -p -[p]> x
// accepted
Loop = (() -[-]> Loop) -[+]> -⊥;
fix = (f: Loop) =[-]> f (() =[-]> f);
_ = fix (self =[+]>
  f = self ();
  f (() =[-]> f)
);
// rejected
Loop = Loop -[p]> ⊥;
fix = (f: Loop) => f f;

// -p -[p]> xS === S -> *;
U = (X:) -> (℘℘X -[-p]> X) -[p]> ℘℘X;
τ: ℘℘U -> U =
  (t: (U -[p]> *) -[-p]> *) =[p]>
  (X:: p) =[p]>
  (f : ℘℘X -[-p]> X) =[p]>
  (p : (X -[-p]> *)) =[p]>
  t ((x : U) =[p]> p (f (x X f)));
σ: U -> ℘℘U = (s: U) => s U τ;
∆ = (y: U) => (p: ℘U) -> σ y p -> p (τ (σ y));: U = τ ((p: ℘U) => (x: U) -> σ x p -> p x);

// p -[p]> -p
Loop = Loop -[+]> -⊥;
fix = (f: Loop) =[+]> f f;

// -p -[p]> -p
// accepted
Loop = (() -[-]> Loop) -[+]> -⊥;
// rejected
fix = (f: Loop) =[-]> f (() =[-]> f);
// accepted
Loop = (() -[-]> Loop) -[+]> () -[-]> +⊥;
fix = (f: Loop) =[-]> f (() =[-]> f) ();
_ = fix (self =[+]> () =[-]>
  f = self ();
  f (() =[-]> f) ()
);

(f => f(() => f)())(self => {
  const f = self();
}

// rejected
Loop = Loop -[p]> ⊥;
fix = (f: Loop) => f f;

id = (A: -p) => (x: A) =[p]> x;
apply = (A: p) => (f: A -[-p]> +⊥) =[p]> (x: A) =[-p]> f x;


Nat = (R: -p) =[p]> (() =[-p]> R) =[p]> (Nat =[-p]> R) =[p]> R;
(_ -[+]> _ -[+]> _): +;
(_ -[-]> _ -[-]> _): -;
((_ -[+]> _) -[+]> _): +;
((_ -[-]> _) -[-]> _): -;

But what if the parameter has a different polarity? Such as

((_ -[+]> _) -[-]> _): ?;
((_ -[-]> _) -[+]> _): ?;

But what if the return has different polarity? Such as

(_ -[+]> _ -[-]> _): ?;
(_ -[-]> _ -[+]> _): ?;

Polar Elimination

Description Conclusion
p. (p p) Polarity is meaningless
p. (p -p) ?
Description Conclusion
p. x -[p]> p ?
p. p -[p]> x ?
p. x -[p]> -p ?
p. p -[p]> -p ?
p. -p -[p]> x ?
p. -p -[p]> p ?
p. -p -[p]> -p ?
// (p -p); p. x -[p]> p
// in this system a function can never be inside of itself?

ALoop = BLoop -> +⊥;
BLoop = ALoop -> -⊥;
fix = (f: ALoop) => f ();

id = p => (A: p) => (x: A) => x;
x = id@+ ((A: -) -> A -> A) id@-;
apply = (A: -p) => (B: p) => (f: A -> B) => (x: A) => f x;


apply : (A: -) -> (B: +) -> (A -> B) -> A -> B;

kid = (A: -p) -> A -> (A -> ⊥) -> ⊥;
x = kid Int 1 ();

incr: +Int -> -Int;
x = apply (Int -> Int) Int incr +1;

Loop = (Unit -> Loop) -> ⊥;
fix = (f: Loop) => f (() => f);

Loop = (() -[-]> Loop) -[+]> -⊥;
Nat = R => (() => R) => (Nat => R) => R;

Inner = (X: p1) => (R: p2) -> (X -> R) -> R;
Nat = (X: p) -> (Inner X -> X) -> X;

zero = (X: p) => (cb: Inner X -> X) =>
  cb (R => )

Opposites Polymorphism

n + = -;
n - = +;

id = @{p}(A: *@{p}) -> A -> A;
apply = @{p,r}(A: *{p}) => (B: *{r}) => (f: A -> B) => (x: A) => f x;

id = (A: +) -> A -> A;
+ = { (P: -) -[+]> + };
- = { (P: +) -[-]> * };

x = R => (n: R -[+]> ('Nat -> ))
x = (f: 'F -[-]> () -[+]> () as ('F: +)) => f f

concat: String -> String -> String;

f x = x;
f 1 === 1;

++False: ? = (A: +*) -> (B: +*) -> A -> B -> B;
+-False: ? = (A: +*) -> (B: -*) -> A -> B -> B;
-+False: ? = (A: -*) -> (B: +*) -> A -> B -> B;
--False: ? = (A: -*) -> (B: -*) -> A -> B -> B;S === S -> *;

fix = (f: (F -> ⊥) -> ⊥ as F) => f f;

U = (X: +□) -> (℘℘X -> X) -> ℘℘X;
b = (X:) => (-f : ℘℘X -> X) => (+p : ℘X) =>
  (+x : U) => p (f (x X f));S === S -> *;
U = (X:) -> (℘℘X -> X) -> ℘℘X;
τ: ℘℘U -> U = (t: ℘℘U) => (X:) => (f : ℘℘X -> X) => (p : ℘X) =>
  t ((x : U) => p (f (x X f)));
σ: U -> ℘℘U = (s: U) => s U τ;
∆ = (y: U) => (p: ℘U) -> σ y p -> p (τ (σ y));: U = τ ((p: ℘U) => (x: U) -> σ x p -> p x);
Zero.z.s => z;
S.x.z.s => s.x;

lazy.f.() => f.();
fix.f => f.(lazy.f)
AddCBV.x.y.r => x.(r.y).(B.y.r);
B.y.r.u => AddCBV.u.(S.y).r;

end: (A: *) -> ⊥;
// p. -p -[p]> x
Loop = (() -[-p]> Loop) -> ⊥;
fix f = f f;

Kid p = (A: -p) -[p]> A -> ()

// p. -p -[p]> p
Kid p = (A: -p) -> A -> ()
Nat = (R: -p) -> R -> (Nat -[-p]> R) -> (R -[-p]> ⊥) -> ⊥;
Zero = (R: p) => (z: R) => (s: _) => (k: R -> ⊥) => k z;
// p. x -[p]> p, (p -p)
Loop = Loop -> ⊥;
fix (f: Loop) = f f;

Loop = (() -> Loop) -> ⊥;
fix (f: Loop) = f (() => f);

id = (A: p) => (x: A) => x;

Kid p = (A: -p) -[p]> A -> (A -[p]> ⊥) -> ⊥;
kid = (A: -p) =[p]> (x: A) => (k: A -[p]> ⊥) => k x;
x: -Kid -> (-Kid -[p]> ⊥) -> ⊥ = +kid -Kid;
x: (-Kid -[p]> ⊥) -> ⊥ = +kid -Kid -kid;

f: (() -[-p]> -T) -[p]> T;

Nat = (R: -p) -> R -> (Nat -[-p]> R) -> (R -[-p]> ⊥) -> ⊥;
Zero = (R: p) => (z: R) => (s: _) => (k: R -> ⊥) => k z;

f n = n 0


f: (A: *) -> (A = A, x: A) -> (A = A, x: A)

X = *;
id (A: *) (x: A) =
  B = A;
  (x: A);

id = (A: *) => (x: A) =>
  ((B: (=A)) => (x: B)) A;

x =
  1 == 2
  | Some eq -> absurd eq
  | none -> "not equal";

M: (A: *, x: A);

id: (A: *) -> A -> A;
X = id A;

((x: *) => x): ((x: *) -> *);
(((x: *) => x) String): ((x: *) -> *);
((s: ((x: *) => x) String) => s): ((s: String) -> String);

(x: (x: *) => x) => x;

((x: *) => x): (x: *) -> *;
(x: (x: *) => x) -> (x: *) -> *;

(((F: * -> *) => (x: F String) => x) ((x: *) => x));
((F: * -> *) -> F String -> F String);

(A = Int, x: A): (A = Int, x: Int);

(A = Int, x: Int): (A: *, x: A);

id = (A: *) => (x: A) => A;

expected :: (A: =Int) -> Int -> A;
received :: (A: *) -> A -> A;

received :: =Int;
expected :: *; // =Int, []

expected :: Int -> Int;
received :: Int -> Int;

expected :: (A: *, x: A);
received :: (B: *, x: B);

((x: *) => x);

X: =Int = Int;
Y: =Int = X;
x = id Int;

(A = Int, x: A);

(x: Int -> Int) => (a: x) => a;

(X: *) => X =>

((X: *) => X) Int;
(M: (X: *) -> *) => M Int;

(x)


((M: (A: *, A)) => M): ((M: (A: *, A)) -> (A = Fst M, Snd M));

  (A, x) = M;
  x;

add = (x, y) => x + y;
add (x, y) = x + y;

Ex = (R: *) => (F: (A: *) -> (x: A) -> R) => F Int 1;

Ex: (R: *) -> (F: (A: *) -> (x: A) -> R) -> R;

((X: *) -> (A: X) => A): (A: *) -> *;
((A: *) => A): (A: *) -> *;

(A = Int, x = 1): (A = Int, x: A)


x : (x: Int) => Int;


equal = (a, b) => a = b;
id = x =>
  y = x;
  print y;
z = 2;

(
  print 1;
  x => x = 1;
  print x;
)

{
  x = 1;
}

let x =
  T_arrow
    {
      var = { Var.id = 0; name = "A" };
      param = T_type;
      return =
        T_arrow
          {
            var = { Var.id = 1; name = "x" };
            param = T_var { var = { Var.id = 0; name = "A" }; type_ = T_type };
            return = T_var { var = { Var.id = 0; name = "A" }; type_ = T_type };
          };
    }

let y =
  T_arrow
    {
      var = { Var.id = 2; name = "A" };
      param = T_type;
      return =
        T_arrow
          {
            var = { Var.id = 3; name = "x" };
            param = T_var { var = { Var.id = 2; name = "A" }; type_ = T_type };
            return =
              T_var
                {
                  var = { Var.id = 3; name = "x" };
                  type_ =
                    T_var { var = { Var.id = 2; name = "A" }; type_ = T_type };
                };
          };
    }

print "Hello World";


True = (A: *, B: *) => A;
True (A: *) (B: *) = A;

Int: {
  Int: *;
  add: Int -> Int -> Int;
} = magic ();

id = (A: *) => (x: A) => x;
x = (x: Int) => x;

(*): (Int -> Int -> Int) &
(*)(1, 2)
(Int: *)

id = A. (x: A) => x;
Id (A: *) (x: A) = x;

id = x => x;
id x = x;

(Value : Value)
(& : *)

(x = 1; x)
(((x: =1) => x) 1);
(Snd (x = 1, x));

(T: *, Eq: T == Int -> Int)
(T = Int -> Int, Eq = Refl);

M = {
  T = Int;
  x = (1: T);
};

x: (T: *, x: T) = (T = Int, x = (1: T));

pair = (A: *) => (B: (T: *) -> *) => (x: B A) => (T = A, x = x);
pair_int_id_one = (T = Int, x = x)

x = (T: *, x: T) => x;

build_m = (T: *) => (X: (T: *) -> *) => (x: X T) => (T = T, x = x);
build_m_int = (X: (T: *) -> *) => (x: X Int) => (T = Int, x = x);
build_m_int_id =  (x: Int) => (T = Int, x = );

pair = a => b => k => k a b;
fst = pair => pair (a => b => a);
snd = pair => pair (a => b => b);

pair = (a: 'A) => (b: 'B 'A) => k => k a b;


empty = 0
[empty] = 0 + 1;
[[empty]] = 0 + 1 + 1;
[[[empty]]] = 0 + 1 + 1 + 1;


Incr = Int -> Int;
Pair = (A: *, A);

incr = ((x : Int) => x);
pair = (A = Int, 1 : A);

Either =
  | Left Int
  | Right String;

rec%List A =
  | Nil
  | Cons (A, List A);

rec%map f =
  | Nil => Nil
  | Cons (el, tl) => Cons (f el, map f tl);


either = Left 1;
(either | Left x => x | Right s => s);

(x : String) => x;
(x : Int) => x;
((A = Int, 1 : A): (A: *, A));
((A = Int, 1 : Int): (A: *, Int));

P = (A = Int, 1 : A);
(A, x) = P;

(T: * = Int; (1: T))
(((T: *) => (1: T)) Int);

x = 1
  : Nat;

(x = 1) => x;

x: 1 = 1;
x + 1;

x : (Value : Type);

id: (x = ⊥ : Int) = (x = ⊥ : Int) => x;

f = (y = ⊥ : Int) => (x : (2, y)) => x;
z = (x = ⊥ : Int) => f 2;
z : 1 : Int = 1;
x = id z

f = (x : Int) => x;
f = (x = 1) => x;

(x = 1; x);
(((x = 1) => x) 1);

(x : Int = 1; x);
(((x : Int) => x) 1)

(x := 1) = 1;
x

(a := x, b := y) = (a = 1, b = 2);

x = 1;
x

Id: {
  initial : Id;
  next : Id -> Id;
} = {

};
(A: * = Int, (Int))

x : Int = 1;

(x = 1) => x;

id = (x: T) => x;
x : Car = id car;

(A: *) => (x: A) => (x: A);

choose {A} {B} (bool: Bool) (a: A) (b: B) =
  bool | true -> a | false -> b;

choose : {A} -> {B} -> Bool -> A -> B -> K;

x = choose true 1 2;

x = 1;
x := 1;

(T = Int, 1 : T)

Color = Red | Green | Blue;

partial_to_int = (color : ((Red | Green) : Color)) =>
  color | Red => 0 | Green => 1;

f = (color: Color) =>
  color
  | (Red | Green) as color => partial_to_int color
  | Blue => -1

T: * = Int;
T = Int;

(T = Int, 1 : T)

Id = {}

id = (A: Prop) => (x: A) => x;
id_id = id ((A: Prop) -> A -> A)

id = {A} => (x: A) => x;
id = x => x;


id = (A: Type) => (x: A) => x;
Id = (A: Type) => A;


(T = Int, 1 : T);

//

(x: t) === (((x: t) => x) x)
(((x: t) => x) x) === x

(x: t = e1; e2) === (((x: t) => e2) e1);

M = {
  T = Int;
  x = 1;
};

x: M.T = 1;

Option {A} =
  | Some A
  | None;

User = {
  id : Nat;
  name : String;
};
eduardo : User = {
  id = 1;
  name = "Eduardo";
};

(((A: *) -> A -> A) : *);
(((A: *) => (x: A) => x) : (A: *) -> A -> A);


((pred : (A: *) -> (x: A) -> (y: A) -> A) => (x: pred Type Int Id) => x)
  ((A: Type) => (x: A) => (y: A) => x) one

Bool = (A: Type) -> A -> A -> A;
true: Bool = A => x => y => x;
false: Bool = A => x => y => y;


f = (pred : Bool) => (x: pred Type Bool Int) => x;

(f: Type -> Type) => (x: id Int) => (y: id Int) =

((X: *) -> X -> X) Int;

M : {
  id : Nat;
  name : String;
} = {
  id = 0;
  name = "Eduardo";
};
M : {
  id : Nat;
} = M;

id = (A : Type) => (x : A) => x;

g = (m : { id : Nat; name : String; }) => f { ...; name : String } g;

g = (m : { id : Nat; name : String; }) =>
  ((m : { id : Nat; name : String; }) => m) g;

f = (A : Row) => (x : Red | Green | Blue | #A ) => x;
g = (x : Red | Green) => f x;

f =
  (company : Bool) =>
  (T : company | false => { ...; cpf : CPF } | true => { ...; cnpj: CNPJ }) =>
  (person : { name : String; ...T }) => person;

f : (A: Row) -> (x : { id : Nat; ...A }) -> A = magic ();
g = (m : { id : Nat;  name : String }) => m;


fix%List A =
  | Nil
  | Cons (A, List A);
List A =
  | Nil
  | Cons (A, @);

rec%Person = {
  id : Nat;
  name : String;
  children : List Person;
};


Person = (id : Nat, (name : String, children : List @))

Bool = (A: Type) => (B: Type) => (C: Type) =>
  (K: Type) -> (A === C -> K) -> (B === C -> K) -> K;
true = (A: Type) => (B: Type) => (C: Type) =>
  (K: Type) => (x: A === C -> K) => (y: B === C -> K) => x refl;

Option = (A: Type) => (none: Bool, none | () => Unit | () => A);
x: Option Int = magic ();
a =
  (none, value) = x;
  none | () => Unit;

List A =
  | Nil
  | Cons (A, @);

T = Type;
Type = 1;

id = ((A: Type) => (x: A) => x) Type;

(A : Type) => A;

((A : Type) => (x : A) => (y : A) => x) Type ((A : Type) -> A) (A : Type, A)

get 1 === get 1
get 1 buf === get 1 buf

A -> B
A : Type  B : Type  E : Row
---------------------------
        A -[E]> B

((m : A -[E0]> B ! Empty) (n : A ! E1)): Either E0 E1

(True | False | ...A)
(... | True | False)

read : Unit -[ Read ]> String;

T = | #A | #B;
x = #A


S = (T : Type, T);

x = S Int 1;

T1 : Type = | A | B | C);
R : Row = ... | B | C;
T2 : Type = | A | ...R;

R : Row = ... | A;
T : Type = ...R | ...R;
T : Type = | A#0 | A#1;
handler :

  (B: Row) ->
  (handler: Unit -[B]> String) ->
  (A: Row) ->
  (K: Type) ->
  (f : Unit -[ Read | ...A ]> K ) -[...A | ...B]> K

Option = | Int | String;

Option.Int


get : Nat -> Unit -<Read | Write> String;
f () : Nat =
  string = get 1 ();
  length string;

get : Nat -> Unit ->
  (K: Type) -> (String -> K) -> String -> K;
f () =
  get 1 () Nat (string => length string)

get 1 === get 1;
get 1 () !== get 1 ();


read : Unit -<Read | Write> String;
read : Unit -[Read | Write]> String;

read : Unit -<Read><Write> String;
read : Unit -[Read][Write]> String;

f : (A: Row) -> (f: Red | ...A) -> Red | ...A;
x = f (...| Red);
x: (f: Red | Red) -> Red | Red);

| Red | Red === | Red

M: {
  X : Type;
  X : String;
  y : X\1;
} = {
  X = Int;
  X = "a";
  y : X = 1;
};


Effect Return =
    | Read : Return = String;


E = (P : Type) => (A : Type) -> A;

f : A -[]> B;


A : Type   B : Type
-------------------
      A -> B

A : Type   B : Type  E : (t: Type) -> Type
------------------------------------------
            A -[E]> B

M : A -[E1]> B ! E2    N : A ! E3
---------------------------------
  M N : B ! A => E1 A | E2 A | E3

A : Type   B : Type  E : (t: Type) -> Type
------------------------------------------
          (x : A) -[E]> B : ⊥

        x : A |- e : B ! E
-------------------------------------
(x : A) => e : (x : A) -[E]> B ! ⊥

M : A -[E]> B ! |    N : A ! |
--------------------------------
  M N : B !



M : A -> B ! E1    N : A ! E2
--------------------------------
   M N : B ! A => E1 A | E2 A

M : A -[E1]> B ! E2    N : A ! E3
---------------------------------
  M N : B ! A => E1 A | E2 A | E3

raise : (E : Type -> Type) -> (R : Type) -> (eff : E R) -> R;
catch : (E : Type -> Type) ->
  (handler: (R : Type) -> (eff : E R) -> R) ->
  (B : Type) -> (f : Unit -[E]> B) -> B

clear : (A : Type) -> (B : Type) -> (f : A -[(R: Type) => (A : *) -> A]> B) -> B =
  catch ((R: Type) => (A : *) -> A) ((R : Type) => (Absurd : E R) => Absurd R)

Ty (A : Type) =
  | Int: Ty Int;

f () =
  x: Int = raise Ty Int Ty.Int;
  x + 1;


x = catch Ty ((R: Type) => (eff : Ty R) => eff | Int => 1) Int f;


A -[((R : Type) => | Read: R = String)]> B
id : Int -> Int;
id : (A : Type) -> A -> A;
((L : Level) -> (A : Type L) -> A -> A);

NatL = (L : Level) -> (A : Type L) -> A -> (A -> A) -> A


(x = 1;
 y;)

id === ∀T. λx : T. x;

|- m : T ! x

Dependent Types

Bool = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;

Never = (A : Type) -> A;

Only_when_true = (A : Type) => (pred : Bool) => pred Type A Never;
f = (pred : Bool) => (x : Only_when_true Int pred) => x

create = (n : Int & n >= 0) => n;

n >= 0
| true = p => create (n & p)
| false p =>
map = {A}  => (f : )

n >= 0 | (true, eq : n >= 0 === true) => create n
(x : Bool, x === true) = true;
x = create n;
x = f false

f : (x : Int) -> ((A : Type) => (x : A) => (y : A) => x) Type Int ((A : Type) -> (x : A) -> A)

(tagged String
  (case "user" { name : String })
  (case "company" { name : String })
  closed) : (user : ({ name : String }) -> )

Macabeus

incr : (x : Int) -> Int = (x : Int) => x + 1;
id = (A : Type) => (x : A) => x;
id = ((x : Int) => x) 1;

Bool = (A : Type) -> A -> A -> A;
true = (A : Type) => (x : A) => (y : A) => x;
false = (A : Type) => (x : A) => (y : A) => y;

add = a => b => a + b;
incr = (x : String) => add 1 x;

When = (pred : Bool) => (A : Type) => pred Type Int Never;
f = (pred : Bool) => (x : debug (pred Type Unit Never)) => x;
x = f true 1;

Id = (A : Type) => A;
x = f false

(x : debug String) => x
IO A =
  | Read : A === String;
read : (file : String) -[| Read]> String = magic ();
print : (msg : String) -[| Print]> Unit = magic ();

world_if_hello : (x : String) -[| Error]> String = (x : String) =>
  x
  | "Hello" => "Hello World"
  | _ => raise (Error "Not Hello");

(x = read "tuturu.txt";
 z = world_if_hello x;
 print z)
  | [%effect Read file] => "Hello"
  | [%effect Error error] => "Error"
  | [%effect Print x] => ()

T : Type;
E : Type -> Type;
x : T ! E

add a b = a + b;
mul a b = a * b;

check : {A} -> (x : A) -> (y : A | y === x) -> Unit;

() = check (add 1 2) 3;
x = (a : Int) => check (mul a 0) 0;
x = (a : Int) => (b : Int) => check (mul a b) (mul b a);

Effects

---------------------
Type L : Type (L + 1)

A : K   B : K
------------------
((x : A) -> B) : K


A : Level   B : A
---------------------
(L : A) -> B : Type (max 0 L)

((A : Type 0) -> A -> A) : Type 1

Bool = (A : Type) -> A -> A -> A;
true = (A : Type) => (x : A) => (y : A) => x;
false = (A : Type) => (x : A) => (y : A) => y;

Id = (A : Type) -> A -> A;
id : Id = (A : Type) => (x : A) => x;

A : Type   B : Type  E : Type -> Type
-------------------------------------
            A -[E]> B

(E : Effect) => (f : Int -[E]> Int) => f;

e ! | === e ! |

get () ! === get ()

x = eq (get ()) (get ());

A -[ | Read: Int ]-> B

(m n : Option Int ! IO)
| None =>
! IO => (handler : Option Int)

Type L : Type (L + 1)

Id = {A} -> A -> A;
id : Id = {A} => (x : A) => x;
x = id id;

Predicativity

U : Type = (A : Type, (A = A, A -> ()) -> ());
V = (A = U, A -> ());

V <= U;
(A = U, A -> ()) <= U;
(A = U, A -> ()) <= U;

U = (L : Level) : Type (L + 1) => (A : Type L, (A = A, A -> ()) -> ());
V = (L : Level) : Type (L + 2) => (A = U L, A -> ());

V L <= U (L + 1);
(A = U L, A -> ()) <= U (L + 1);
(A = U L, A -> ()) <= U L;

M = {
  T : Type;
  x : T;
};

((L : Level) -> Type L : Type (L + 1)) : Type 1


S : Type = (T : Type, Unit);
M : S = (T = S, ());

Type 0 : Type 1
(X : Type 0) => Type 0;

Int : Type 0
((x : Int) -> Int) : Type 0

S : (L : Level) -E> Type (L + 1) : Type 1 = (T : Type, Unit);
M : S = (T = S, ());

S : (L : Level) -E> Type (L + 1) = (L : Level) => (T : Type L, Unit);
M : (L : Level) -E> S (L + 1) = (L : Level) => (T = S L, ());


S : (L : Level) -> Type L = (L : Level) => (T : Type L, Unit);
M : (L : Level) -> S L = (L : Level) => (T = S L, ());

S : Type 1 = (L : Level) -> (T : Type L, Unit);

A : Type 1 = (L : Level) -> Type L;
S : Type 1 = (T : (L : Level) -> Type L, Unit)

M = (T = (L : Level) -> S L, ());

x = (L : Level) : Ex (L + 1) => (T : (LT : Level) -> Type LT = Ex L, T)


loop : Unit ->! Unit;
soundness + strong normalizing = consistency


map : ('A -> 'B) -> List 'A -> List 'B;

id : (T : Type -> Type) -> (A : Type) -> A -> T A;

call_id (id : {A} -> A -> A) =
  x = id "a";
  y = id 1;
  (x, y);

Id = (A : Type) => A;
f = (T1 : Type) => (T2 : Type -> Type) => (x : T2 T1) => x;
x : Int = f Int Id 1;

Id = (L : Level) => (A : Type L) => Type L;
f =
  (L : Level) =>
  (T1 : Type L) =>
  (T2 : (L : Type) -> Type L -> Type L) =>
  (x : T2 L T1) => x

Id : Type 1 = Unit A;
Const = (L : Level) => (_ : Type L) => Type L;

f = (L : Level) => (x : Type L) => x;

f =
  (L : Level) =>
  (F : (L : Level) -> (K : Type L) -> Type L -> ((T : Type L) -> K) -> K) =>
  F ((T : Type L) => (x : T) => x)
  (x : T L Int) => x;

Id : Type 1 = (L : Level) -> (A : Type L) -> A -> A;

Level : Type 1
Type : (L : Level) -> Type (L + 1)


id  = (A : Type 0) => (x : A) => x;

Prop : Type 0
Set : Type 0
Level : Type 0

Level  : Type 0
Type 0 : Type 1

Empty = Type 0


Int : Type 1;
String : Type 2;

F = (L : Level) => (A : Type L) => (B : Type L) => (x : A) -> B;

T : Type 1 = (L : Level : Type 1) -> Int;

Type : (L : Level) -> Type (L + 1)

S : Type 1 = (L : Level, Type L);

X : Type 1 = Level;
Id : Type 1 = (L : Level : Type 1) -> (A : Type L) -> A -> A;
id = (L : Level) => (A : Type L) => (x : A) => x;
x = id 1

Id : Type 1 = (L : Level) => L;

Id : Type 1 = (A : Type 0) -> A -> A;
Id : Type 2 = (A : Type 1) -> A -> A;
id = (A : Type 0) =>

Type : (L : Level) -> Type (L + 1);

x : R = (_ : P -> R) (_ : P);
x : Type 2 = Type 1


    A : Type A_L      B : Type B_L
-----------------------------------------
(x : A) -> B : Type (max A_L B_L[x := 0])

max (a + 1, a) === a + 1
max (a, b) a === max a b

x : (L : Level) -> Type (L + 1) : Type 1;
x = (L : Level) => Type L;

U = (L : Level) : Type (L + 1) => (A : Type L, (A = A, A -> ()) -> ());
V = (L : Level) : Type (L + 2) => (A = U L, A -> ());

V L <= U (L + 1);
(A = U L, A -> ()) <= U (L + 1);
(A = U L, A -> ()) <= (A : Type (L + 1), (A = A, A -> ()) -> ());
(A = U L, A -> ()) <= (A = U L, (A = A, A -> ()) -> ());


SK : (L : Level) -> Type (L + 1) = (L : Level) => (A : Type L, Unit);
S : Type 1 = (L : Level) -> SK L;
M = (L : Level) => (A = S, ());

M = (L : Level) : Type (L + 2) => (A = (A : Type L, A), ());

M : Type 2 = (A : Type 1 = (A : Type 0, A), ());

F : Type L = (A : _ : Type L) -> (_ : Type L)
S : Type L = (A : _ : Type L, _ : Type L)

F : Type = (K : Type) -> (f : (A : Type) -> A -> K) -> K;

f = (K : Type) => (f : (A : Type) -> A -> K) => f ((A : Type 0) -> (x : A) -> A) ((A : Type 0) => (x : A) => x);

F : Type 1 = (L1 : Level) -> (K : Type L1) -> (f : (L2 : Level) -> (A : Type L2) -> A -> K) -> K;
f = (L1 : Level) => (K : Type L1) => (f : (L2 : Level) -> (A : Type L2) -> A -> K) =>
  f (lsucc lzero) ((A : Type 0) -> (x : A) -> A) ((A : Type 0) => (x : A) => x)

x = (L : Level) =>

f = (K : Type) => (f : (A : Type) -> A -> K) => K;



id : (A : Type) -> A -> A;
id (A : Type) (x : A) = x;

x = id Int 1;

id : {A : Type} -> A -> A;
id {A : Type} (x : A) = x;

id : 'A -> 'A;
id x = x;

x = id 1;

incr (x : Int) = x + 1;

id : forall A. A -> A;
id : forall A where A extends Object;


M : {
  T = Int;
  x : Int;
} = {
  T = Int;
  x = 1;
};
M1 : {
  T : Type;
  x : T;
} = M;

id : (A :> Int) -> A -> A;


uip : forall x y (a b : x = y), a = b

heteregenous : forall x1 y1 x2 y2 (a : x1 = y1) (b : x2 = y2), a = b;


ext : forall A B (f g : A -> B) -> (forall x, f x = g x) -> f = g = magic id;

S : Type = (T : Type, Unit);
M1 : S = (T = S, ());
M2 : S = (T = (typeof M1), ());

S : (L : Level) -> Type (L + 1) = (L : Level) => (T : Type L, Unit);
M1 : (L : Level) -> S (L + 1) : Type 2 = (L : Level) => (T : Type (L + 1) = S L, ());
M2 : (T : Type 2, Unit) : Type 3 = (T = (typeof M1), ());


M : (L : Level) -> ((T : Type L, Unit)) = (L : Level) => (T : Type (L + 1) = S L, ());


Int : Type
String : Type

Type : Type

id = (A : Type) => (x : A) => x;

Bool = (A : Type) -> A -> A -> A;
true = (A : Type) => (x : A) => (y : A) => x;
false = (A : Type) => (x : A) => (y : A) => y;

Never = (A : Type) -> A;

f = (pred : Bool) => (x : pred Type Int Never) => x;
a = f true;
a = (x : Int) => x;
b = f false;
b = (x : Never) => x;

Type 0 : Type 1
Type 1 : Type 2

Type : Kind

Id : Type = (A : Type) -> A -> A;



A : _   B : K
--------------------
  (x : A) -> B : K

A : K   B : K
--------------------
(x : A) -> B : K[x := 0]


Type 0 : Type 1
Type L : Type (L + 1)

Id : Type 1 = (A : Type 0) -> A -> A;
id0 = (A : Type 0) => (x : A) => x;
id1 = (A : Type 1) => (x : A) => x;
x = id1 ((A : Type 0) -> A -> A) id0;

Id : Type 1 = (L : Level) -> (A : Type L) -> A -> A;
id = (L : Level) => (A : Type L) => (x : A) => x;

id = id 1 Id id;

z = (T = Int, x : T = 1);

id = (K : Kind) => (A : K) => (x : A) => x;

x = id ((A : Type) -> A -> A);


S : Type = (T : Type, Unit);
M : S = (T = S, ());

S2 = (T : S, Unit);
M : S2 = (T = S2, ());

S : (L : Level) -> Type (L + 1) = (L : Level) => (T : Type L, Unit);
M : (L : Level) -> S (L + 1) = (L : Level) => (T = S L, ());

S2 : (L : Level) -> Type (L + 2) = (L : Level) => (T : S L, Unit);
M2 : (L : Level) -> S2 (L + 1) = (L : Level) => (T = S2 L, ());

Bool = (A : Type) -> A -> A -> A;
true = (A : Type) => (x : A) => (y : A) => x;
false = (A : Type) => (x : A) => (y : A) => y;

max A_L (max B_L B_L) = max A_L B_L
Never = (A : Type) -> A;

Only_when = (pred : Bool) => (A : Type) => pred | true => A | false => Never;
f = (pred : Bool) => (x : Only_when pred Int) => x;


id = (L : Level) => (A : Type L) => (x : A) => x;

Erasable Universe Polymorphic Predicative System F

Hypothesis, System U is equivalent to this system, but where levels can be recursive.

Var = String;
Level = Nat;

Kind =
  | KType (level : Level)
  | KLevel;
Type =
  | TVar (x : Var)
  | TArrow (param : Type, return : Type)
  | TForall (var : Var, param : Kind, return : Type);
rec%Expr =
  | EVar (x : Var)
  // term abstraction
  | ETAbs (var : Var, param : Type, body : Term)
  | ETApp (lambda : Term, arg : Term);
  // type abstraction
  | EKAbs (var : Var, param : Kind, body : Term)
  | EKApp (lambda : Term, arg : Type);

Effects

read : String -[IO]> String;

Inference

id : {L} -> {A : Type L} -> A -> A : Type 1;

id1 : _A -> _A : Type _L1 && _L1 : Level && _A : Type _L1
id2 : _B -> _B : Type _L2 && _L2 : Level && _B : Type _L2

_A = _B -> _B

(_B -> _B) -> _B -> _B
id = id id;

map : (Int -> Int) -> ();

id2 : _B -> _B : Type _L2 && _L2 : Level && _B : Type _L2

x = map id;
id >= Int -> Int

Id = {L} -> {A : Type L} -> A -> A
f : {A : Type | A :> Id} -> A -> A;

incr : Int -> Int;
(_A -> _A) <: Int -> Int;
x = f incr;

Induction

Rec = (G : Type -> Type) => (X : Type) -> (G X -> X) -> X;


Unit = (A : Type) -> A -> A;
unit : Unit = A => x => x;
Elim = (P : Unit -> Type) => (v : P unit) => (U : Unit) => P U
Elim = (P : Unit -> Type) -> P unit -> (U : Unit) -> P U;


f = (p : (tag : Unit, tag Type String)) => (
  (tag, payload) = p;
  tag String payload;
);


Tag  =
  (H : Type) ->
  (A : Type) ->
  (B : Type) ->
  (R : Type) ->
  ((Left : H === A) -> R) ->
  ((Right : H === B) -> R) ->
  R;

Bool = (A : )
tagged =
Status = tagged ((tag : Bool) => tag Type Int String);

to_string = (status : Status) => (
  (tag, content) = status;
  tag String
    (_h_eq_unit => "valid")
    (h_eq_string => subst h_eq_string content)
);


Bool = (R : Type) ->
bool | true  =>





Nat = Rec ((X : Type) => (R : Type) -> R -> (X -> R) -> R);

Status = (valid : Bool, valid Type Unit String);

f = status = | Valid => "valid" | Invalid (reason) => reason;

f = (tag : Bool) => (value : tag Type String String) => (
  tag
    ("valid" : tag Type String String)
    (value : tag Type String String)
);

Nat = (L : Level) Rec (X => (R : Type L) -> )


Bool = (A : Type) -> A -> A -> A;
Status = (tag : Bool, pred Type Unit String);

Bool =
  (H : Type) ->
  (T : Type) ->
  (F : Type) ->
  (R : Type) ->
  ((H_eq_T : H === T) -> R) ->
  ((H_eq_F : H === F) -> R) ->
  R;

Tag =
  (H : Type) =>
  (T : Type) =>
  (F : Type) =>
  (R : Type) ->
  ((H_eq_T : H === T) -> R) ->
  ((H_eq_F : H === F) -> R) ->
  R;

Either = (A : Type) => (B : Type) =>
  (H : Type, (tag : Tag H A B, H));

Status = (tag : Bool, tag Type Int String)

Either A B = {R : Type} -> !(Left : A -> R, Right : B -> R ) -> R;

Option A =
  | None
  | Some A;

Option A =
  tagged [
    case #None Unit;
    case #Some A;
  ];

to_string = (string_or_int : Either String Int) =>
  string_or_int
  | Left = s => s;
  | Right = n => Int.to_string n;

to_string = (string_or_int : Either String Int) =>
  [%match string_or_int
  | (#Left, (#Left, s)) => s
  | (#Right, (#Right, n)) => Int.to_string n]
to_string = (string_or_int : Either String Int) =>
  string_or_int
  | Left (Left _) => s
  | Right (Right _) => Int.to_string n]
to_string = (string_or_int : Either String Int) =>
  string_or_int
  | (#Left, s) => s
  | (#Right, n) => Int.to_string n;

[%match (a, b) with
| (true, b) => b;
| (false, _) => false;
];

(Bool [@variant]) = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;

(A : Type & P A);
(A : Type & A === Int);
(A : Nat & Gte A 0);

Level : Type 1;
Type 0 : Type 1;
Type L : Type (L + 1);


Pair A B =
  (R : Type) -> ((tag : A) -> (content : B tag) -> R) -> R

f = (p : Pair Bool (tag => tag Type Int String)) =>
  p
    (a : Type &
      p Type (tag => _ => tag Type Int String)
    (tag => content => content):

f = (p : (A : Bool, tag Type Int String)) => (
  (tag, content) = p;
  content;
):
F = (p : (A : Bool, tag Type Int String)) -> (
  (tag, content) = p;
  tag Type Int String
);

Tag =
  (H : Type) =>
  (T : Type) =>
  (F : Type) =>
  (R : Type) ->
  ((H_eq_T : H === T) -> R) ->
  ((H_eq_F : H === F) -> R) ->
  R;

Either = (A : Type) => (B : Type) =>
  (H : Type, (tag : Tag H A B, H));
to_string = (a : Either String String) => (
  (H, (tag, payload)) = tag;
  tag String
    (H_eq_T => subst H_eq_T _ payload)
    (H_eq_F => subst H_eq_F _ payload)
);

Intersection

--------------
(x : A) & B

S : Type & Equal S {
  a : String;
} = {
  a : String;
};
Nat : (Nat : Type & {
  zero : Nat;
}) = _;

x = id Nat;


Type : Type
-> : Function
{} : Record

f = (A : Type) => (B : Type) =>   & B;

expected : A;
received : A & B;

(==) :
  ((==) : {A : Type} -> (l : A) -> (r : A) -> Type) &
  ({A : Ord} -> (l : A) -> (r : A) -> Option (l == r));

(>=) :
  ((l : Nat) -> (r : Nat) -> Type) &
  ((l : Nat) -> (r : Nat) -> Option (l >= r));

length : (s : String) -> Nat;

create = (len : Nat & len >= 1) => ();
x = create 4096;

g = x =>
  [%match x >= 1
  | Some x_gte_one => f (x & x_gte_one)
  | None => ()
  ]

Option : (Option : _ & {
  some : {A} -> Option A;
});

Nat : {
  zero : Nat;
};

Nat : (Nat : _ & {
  zero : Nat;
})
Nat : (Nat : _ & {
  zero : Nat;
}) = _;

x : Nat = Nat.zero;

(x => x : {A} -> A -> A)

(1, 2, 3)
(z = 1, x = 2, z = 3);

f : !(x : Int) => Int;

x =
  x = 1;
  f (x = x);

(a : Int) -> Int
(a : Int) -> Int
((a : Int)) -> Int
((x : A & y : B), )

z = (x : Int, y : Int)

Id = (A : Type) => A;
id : Type & (A : Type) => Type;

Point : Type & (Type, Type) = (Int, Int);
x = (Int, Int)

f : Type & {A} => Type & {T} => (x : {A : T}) => T;


Id #= {A} => (x : A) => A;


Point : Type & (Type, Type) = (Int, Int);
T = {
  T = Int;
};

{R} -> {S : R } -> {A : S} -> (l : A) -> (r : A) -> R



((x : Int) => x : (x : Int) => Int);
(lambda arg)

(x : Int, y : Int);
(x = 0, y = 0);
((x, y) = p; z)

(Int, Int)
(0, 0) : (Int, Int)


x : Int & String;
z : String = x;

Nat : (Nat : Type & {
  zero : Nat;
}) = _;

zero : Nat = Nat.zero;

Point : Type & (Type, Type) = (Int, Int);

Point = (Int, Int);


Point : Type = (x : Int, y : Int);

f = (a : Int, b : Int) => a + b;

x = f (a = 1, b = 2);
x = f (1, 2);

(==) :
  {A} -> (a : A) -> (b : A) -> Type &
  {A : Eq} -> (a : A) -> (b : A) -> Option (a == b));


(>=) :
  {A} -> (a : A) -> (b : A) -> Type &
  {A : Ord} -> (a : A) -> (b : A) -> Option (a >= b))

f = (a : Nat & a >= 1) => ()

Nat : {
  zero : Nat;
}
l : Type & Option (1 == 2) = 1 == 2;

(==) : {A : Eq} -> (a : A) -> (b : A) -> Bool;

f = (a : Nat & a == 1) => ()



z = (x : Nat) =>
  x == 1
  | Some x_eq_1 -> f (x & x_eq_1)
  | None -> raise "x is not 1";

Nat : {
  zero : Nat;
} = _;

zero : Nat = Nat.zero;

(-) :
  (x : Nat) -> Int &
  (a : Int) -> (b : Int) -> Int &
  ();

expected :: Arrow Nat Int;
received :: Arrow Int Nat;`

(==) :
  {A} -> (a : A) -> (b : A) -> Type &
  {A : Eq} -> (a : A) -> (b : A) -> ?(a == b));

f = (a : Int | String) => a;
f = (a : Type & Either (A == Int) (A == String)) => a;

(==) #: {A} -> (a : A) -> (b : A) -> Type;
(==) :: {A : Eq} -> (a : A) -> (b : A) -> ?(a == b);


Nat : {
  zero : Type;
} = _;

T #= Int;
x := 1;


a : Int & String = (1 & "a");
a : Int | String = 1;

f = (a : A) => a;

x =
  tagged String
    (case );

Option =
  | Some {A} (value : A) : Option A
  | None {A} : Option A;
Option : (Option : Type -> Type) & {
  Some : {A} -> (value : A) -> Option A;
  None : {A} -> Option A;
};

Nat : (Nat : Type) & { zero : Nat } = _;
zero : Nat = Nat.zero;


some_nat : Option Nat = Option.Some Nat.zero;

Eq = (Eq : Type) & {
  equal : (a : Eq) -> (b : Eq) -> Bool
};

(==) :
  {A} -> (l : A) -> (r : A) -> Type &
  {A : Eq} -> (l : A) -> (r : A) -> Option (l == r);

x : Type _&_ Option (l == r) = a == 1;
f = (a : Nat) => (a_eq_1 : a == 1) => ();

zero : Int = Int.zero;

id : (x : Int) -> Int = (x : Int) => x;
id = (A : Type) => (x : A) => x;

g = (a : Nat) =>
  a == 1
  | Some a_eq_1 -> f a a_eq_1
  | None -> raise Error;

g = (a & a == 1) {

};
f = a =>
  a == 1
  | a_eq_1?
  | () =>

Option {A} =
  | Some (value : A)
  | None;
Option : {A : Type} -> (Option : Type) & {
  Some : (value : A) -> Option;
  None : Option;
} = _;
Option : (Option : Type -> Type) & {
  Some : {A : Type} -> (value : A) -> Option A;
  None : {A : Type} -> Option A;
} = _;

Ad Hoc Polymorphism

Overloading for propositions and value.

// overloaded ==
f = (a : Nat) (a_eq_1 : a == 1) => a;
() =
  a == 1
  | Some a_eq_1 => f a a_eq_1
  | None => raise Error

// overloaded module
Nat : {
  zero : Nat;
} = _;
zero : Nat = Nat.zero;

Namespacing

This creates two namespaces, this allows to define things to be used both as a proposition and a value.

(==) #: {A} -> (l : A) -> (r : A) -> Type;
(==) :: {A : Ord} -> (l : A) -> (r : A) -> Option (l == r);

Nat #: Type;
Nat :: { zero : Nat };

This leads to a problem with dependent types where you may want to reference the value on the type level, so new operators are needed, but it works nicely for many cases.

While ugly, it is also quite predictable. And make it closer to a traditional ML.

Intersection Types

This uses of subtyping to allow two values to be packed together, it acts like a pair where the unpacking may happens implicitly.

(==) :
  ((==) : {A} -> (l : A) -> (r : A) -> Type) &
  {A : Ord} -> (l : A) -> (r : A) -> Option (l == r);

Nat : (Nat : Type) & { zero : Nat };

This leads to problems with decidability and also with function application, statements such as 1 == 2 can be interpreted as two different functions being called, this can be limited and detected in an ad hoc manner.

This is quite cute when being used, we keep the notion of a single namespace and it can be extended to things such as constrained types (a : Nat & a == 1) => a, it acts as a dual of pairs in the presence of subtyping.

Substructural Types

Never = (A : Type) -> A;
Id = (A : Type) -> (x : A) -> A;

Id = (A : Type) ->
  Type.clone A (A1 => A2 => (x : A1) -> A2);

x = Id

Type : Type;

id = (L : Level) => (A : Type L) => (x : A) => x;

create = (A : Type) -> (x : A) -> A;
create = (x : Int : Resource) => (x_eq_0 : Eq x 0) => x;

create = (x : Rc Int) =>
  (x1, x2) = clone x;
  (x_eq_0 : Eq x1 0) => x2;


f = (x : Int) =>
  eq x 0
  | Some (x, x_eq_0) -> create x x_eq_0
  | None -> raise Error

(x : Rc Int) =>
  (x1, x2) = clone x;
  x1 + x2;

(x : )

Bounded Quantification

Not T = (A <: T) -> A;

Theta = (A <: Top) -> Not ((B <: A) -> Not B);

f = (A0 <: Theta) => (A0 <: (A1 <: A0) -> Not A1);

context = [A0 <: Theta];
received :: A0;
expected :: (A1 <: A0) -> Not A1;

context = [A0 <: Theta];
received :: (A1 <: Top) -> Not ((A2 <: A1) -> Not A2);
expected :: (A1 <: A0) -> Not A1;

context = [A0 <: Theta; A1 <: A0];
received :: Not ((A2 <: A1) -> Not A2);
expected :: Not A1;

context = [A0 <: Theta; A1 <: A0];
received :: (A2 <: Top) -> Not ((A3 <: A2) -> Not A3);
expected :: (A2 <: A1) -> Not A2;

Not T = (A <: T) -> A;
Theta = (A <: Top) -> Not ((A <: A) -> Not A);

context = [A <: Theta];
received :: A;
expected :: (A <: A) -> Not A;

// predicativity
Not T = (A <: T) -> A;
Theta : Top 1 = (A <: Top 0) -> Not ((A <: A) -> Not A);

context = [A <: Theta];
received :: A;
expected :: (A <: A) -> Not A;

context = [A <: Theta];
received :: (A <: Top 0) -> Not ((A <: A) -> Not A);
expected :: (A <: A) -> Not A; // clash

// universe polymorphism + eta
context = [A <: Theta];
received :: A;
expected :: (A <: A) -> Not A;

context = [A <: Theta];
received :: (L : Level) -> (A <: Top L) -> Not ((A <: A) -> Not A);
expected :: (A <: A) -> Not A; // eta

context = [A <: Theta];
received :: (A <: Top 1) -> Not ((A <: A) -> Not A);
expected :: (A <: A) -> Not A;

context = [A <: Theta; A <: A];
received :: Not ((A <: A) -> Not A);
expected :: Not A;

context = [A <: Theta; A <: A];
received :: A;
expected :: (A <: A) -> Not A;

Linear by default

Value L <: Resource L;

id = (A : Resource) => x => x;

fix%map = (f : 'A -> 'B, l : List 'A) =>
  l
  | [] => []
  | hd :: tl =>

ADTs

Either A B =
  | Left (x : A)
  | Right (x : B);

Either A B =
  | (tag : "left", x : A)
  | (tag : "right", x : B);

Tag = "left" | "right";

is_left = (s : String) -> (tag == "left") Option;

A | B <: C
  A <: C && B <: C

C <: A | B
  C <: A || C <: B;

A & B <: C
  C <: A || C <: B

C <: A & B
  C <: A && C <: B
expected :: C
received :: A & B

expected :: Nat | 1
received :: 0

expected :: String
received :: "left" | "right"

"left" | "right" <: String

Either = (A, B) =>
  | Left (x : A)
  | Right (x : B);

Either = (A, B) =>
  | (#Left, x : A)
  | (#Right, x : A);

f = (x : Either Int String) =>
  x
  | (#Left, x) => x + 1
  | (#Right, x) => 0;

Either = (A, B) =>
  | { tag : "left"; x : A; }
  | { tag : "right"; x : B; };

f = (x : Either Int String) =>
  x
  | { tag : "left"; x}
  | Neq


Person = {
  id : Nat;
  name : String;
  gender : Gender;
};
Company = {
  id : Nat;
  name : String;
};

// ML like
User =
  | Person (person : Person)
  | Company (company : Company);

name = (user : User) =>
  user
  | Person person => person.name
  | Company company => company.name;

// TypeScript
User =
  | { tag : "person"; person : Person; }
  | { tag : "company"; company : Company; };
name = (user : User) =>
  user.tag == "person"
  ? user.person.name
  : user.company.name;

// TypeScript + Pattern Matching
User =
  | { tag : "person"; person : Person; }
  | { tag : "company"; company : Company; };
name = (user : User) =>
  user
  | { tag : "person"; person } => person.name
  | { tag : "company"; company } => company.name;

// TypeScript + Pairs + like
User =
  | ("person", person : Person)
  | ("company", company : Company);
name = (user : User) =>
  user
  | ("person", person) => person.name
  | ("company", company) => company.name;

// TypeScript + Pairs + labels
User =
  | (#Person, person : Person)
  | (#Company, company : Company);
name = (user : User) =>
  user
  | (#Person, person) => person.name
  | (#Company, company) => company.name;

// Dependent Types like
User =
  (tag : "person" | "company",
    payload : tag | "person" => Person | "company" => Company);
name = (user : User) =>
  (tag, payload) = user;
  tag
  | "person" => payload.name
  | "company" => payload.name;

(Nat : Type) & { zero : Nat; }

Either A B =
  | Left (x : A)
  | Right (x : B);

Bool = (A : Type) -> A -> A -> A;
Either A B = (tag : Bool, tag Type A B);

Either A B =
  | (tag : true, A)
  | (tag : false, B);

true <: Bool

f = (x : true : Type) => x;

z = (x : Bool) => x;
l = z (true : Bool);

k : Type & Bool = true;

Nat : (Nat : Type) & {
  zero : Nat;
} = _;

zero : Nat = Nat.zero;

User = {
  id : Nat;
  name : String;
};

x : Type _&_ Bool = true;
l : Type = x;

T : Type = (Int, Int);

type T = (Int, Int);

(x : Int) |

Sum Types

Either A B =
  | Left (x : A)
  | Right (x : B);

Bool = (A : Type) -> A -> A -> A;
Either A B = (tag : Bool, x : tag Type A B);

Either A B =
  | (true, x : A)
  | (false, x : B);

Either A B =
  (tag : Bool, x : tag ? A : B);

f = (x : Either Int String) =>
  x
  | ("left", x) => true
  | ("right", y) => false;


x : Bool : Type = true;
x : true : Type = true;

true : Bool.Value & Bool.Resource & Type;

User = {
  id : Nat;
  name : String;
};
eduardo = {
  id = 0;
  name = "a";
};

Show = {
  show : (x : Show) -> String;
};

Type
Resource
(x => x);
(x, y);
(x == y);
(x & y);
(x | y);


Nat = (Nat : Type) & { zero : Nat; }

(X : String) | Int;

(T : Type) | Eq T T;


Option = A => | Some (x : A) | None;
Option = A =>
  | (#Some, A)
  | (#None, Unit);

x = ("some", 1);

f = (x : Nat & x == 0) => {
  z = x + 1;
};

magic = (x : A) => (a_eq_b : A == B) : B => subst eq X;

true : Bool _&_ Type;

f = (A : Type & A <: Int) => (x : A) => x;

f = z =>
  z
  | x => x
  | y => y;

Either A B = {K} ->
  (left : (x : A) -> K, right : (x : A) -> K) -> K;

f = either =>
  either (
    left = x => x,
    right = x => x
  )

(x : A & y : B)
(A & B)

Nominal

Either A B #=
  | ("left", x : A)
  | ("right", x : B);

F := (A : Type) => #A;

X = F Int;
Y = F Int;

Option A #=
  | ("some", A)
  | "none";

x : _("some", 1) = ("some", 1);

rec%Tree R =
  | ("var", var : String, ...R)
  | ("lam", param : String, body : Tree, ...R)
  | ("app", lambda : Tree, arg : Tree, ...R);

Parse_tree #= Tree (...,);
Typed_tree #= Tree (..., type : Type);

Bool #= (A : Type) -> (x : A, y : A) -> A;
true : Bool = (A : Type) => (x : A, y : A) => x;
false : Bool = (A : Type) => (x : A, y : A) => y;

T #= Int;

x : _("left", x : A) = ("left", 1);
x : Either Int String = x;
x : ("left", x : A) = x;

l : _(1, 1) = (1, 1);

Example self_app : Uexp := fun var => UAbs (var := var)
    (fun x : var => UApp (var := var) (UVar (var := var) x) (UVar (var := var) x)).

(x => A => (y : A) => (A => (x : A) => (y : A) => x))


System F + Omega + Module + Inference ->
System F + Omega + Eta + Module + Inference ->
Impredicative CoC + Type : Type + Sigma + Inference ->
Erasable Universe Polymorphic CoC + Sigma + Inference ->
Erasable Universe Polymorphic CoC + Sigma + Identity + Inference ->

Erasable Universe Polymorphic CoC
+ Sigma
+ Identity
+ Inference
+ Record
+ Pattern
+ Nominal
+ Literal
+ Intersection
+ Union;

T #=
  | ("left", x : Int)
  | ("right", x : String);

f = (t : T) =>
  t
  | ("left", x) => ()
  | ("right", x) => ();
Bool = (A : Type) -> (x : A) -> (y : A) -> A;
true = (A : Type) => (x : A) => (y : A) => x;
false = (A : Type) => (x : A) => (y : A) => y;

sequence : {A} ->> {B} ->> (x : A) ->> (y : B) ->> B = _;

sequence = {A} => (x : A) => {B} => (y : B) => _;
sequence = {A} => {B} => (x : A) => (y : B) => _;

f = x => A => (x : A);
f = id => (id 0, id "a");

f = (x) => x;

sequence = _A0 => (x : _A) => _B1 => (y : _B) => x == y;
sequence = _B => (x : _B) => _B => (y : _B) => x == y;
Id : Type -> \0 -> \1;
Id : (A : Type) -> (x : A) -> A = _;
Id : (B : Type) -> (y : B) -> B = _;

id : (A : Type) -> (x : A) -> A = _;

f_int_or_string :
  (pred : Bool) -> (x : pred Type Int String) -> pred Type Int String;
l : (x : Int) -> Int = f_int_or_string true;
x : (x : Int) -> Int = _ = id Int

f = (x : _A0) => (x : Type) => (x : A1)

id : (A : Type) -> A -> A;

(x : _p) -> \0 -> \1
(A : Type) ->  -> A;

_p = Type
x\0
A\x

_r = x

((x : _p) -> _r) (Int : _p)


occurs _A0 _B1
f = x => (A : Type) => (x : A)
y = (B : Bool) => (x : B) => x

((a, b) = p; (b : A)) : ((a, b) = p; A)

((x : _A) => x + 1) : (x : Int) -> Int;

Prop : Type 0

Bool : Prop = (A : Prop) -> A -> A -> A;

f = (pred : Bool) => (x : pred Prop Bool String) => x;

f1 = p => (
  ((A, x) = p; ) : ((A, _) = p; A)
);
f2 = p => (
  (A, x) = p;
  x
);
((x : T) => e1)

Unification

(A:level):index
(_A:level):index
((A:level):offset):index

id:

(_HOLE\current)\was\distance
(A : Type) -> _C -> () -> (A\1 -> A\2)     -> _C;
(X : Type) -> _C -> () ->         _B\2\2\0 -> _B\2\2\2;


(X : Type) -> _C -> () -> (A\1 -> A\2)\2\2\0 -> (A\1 -> A\2)\2\2\1 -> (A\1 -> A\2)\2\2\2;
(X : Type) -> _C -> () -> (A\1 -> A\2)\2\2\0 -> (A\1 -> A\2)\2\2\1 -> (A\1 -> A\2)\2\2\2;


(_C\1\1)\0 -> A\1        -> (_C\1\1)\3;
(_C\1\1)\0 -> (_B\2\2)\0 -> (_B\2\2)\1

(_C\1\1)\0 -> A\1           -> (_C\1\1)\3;
(_C\1\1)\0 -> ((A\1)\1\2)\0 -> ((A\1)\2\2)\1;

(((A\1)\1\2)\1\1)\0 -> A\1           -> (((A\1)\1\2)\1\1)\3;
(((A\1)\1\2)\1\1)\0 -> ((A\1)\1\2)\0 ->  ((A\1)\1\2)\1;

A\0 -> A\1 -> (A\3)\3;
A\0 -> A\1 -> ((A\1)\1\2)\1;

(x\0) => (y\1) => (x\1)

(_C\1)\0 -> A\1    -> (_C\1)\3;
(_C\1)\0 -> (_B\2) -> (_B\2);

(A : Type) -> A
(B : Type) -> B

A = 0
B = 0

_A = Var
(T)\offset = Link



(x : _A) => (y : _B) => (x : _B\1 -> _B\1);

_A : 0
_B : 1

expected : _A : 2
received : _B\1 -> _B\1 : 0

_A := (_B\1 -> _B\1) : 0

hole : _A
hole_offset : 2
in_offset : 0
in_: _B\1

hole : _A
hole_offset : 2
in_offset : 1
in_: _B\0

_B\1 = hole_offset - in_offset

H := T\(T_offset - H_offset + level H - min_level T)
_B\0 := _A\(2 - 0)\0

(A : Type) -> _A -> (A\2 -> A\3) -> _A\2;
(X : Type) -> _C ->           _B -> _B\1;

(A : Type) -> _A -> (A\2 -> A\3) -> _A\2;
(X : Type) -> _A ->           _B -> _B\1;

(A : Type) -> _A -> (A\2 -> A\3) -> _A\2;
(X : Type) -> _A -> (A\2 -> A\3) -> (A\2 -> A\3)\1;

(A : Type) -> _A -> (A\2 -> A\3) -> _A\2;
(X : Type) -> _A -> (A\2 -> A\3) -> (A\2 -> A\3)\1;

(A : Type) => (x : A\1) => x;
(A : Type) -> (x : A\1) -> A\2;

(x : _X) => (A : Type) => (x : A)

_X : 0

expected : A\1 : 0
received : _X : 2


expected_offset : 0
expected : _A\2
received_offset : 0
received : (A\2 -> A\3)\1

expected_offset : 2
expected : _A
received_offset : 0
received : (A\2 -> A\3)\1


expected : _A -> _A\1
received : _B -> (_C -> _C)

expected : _A -> _A\1
received : _A -> (_C -> _C\1)

_A := (_C -> _C\1)

_A := (A\2 -> A\3)\1\-2

_A\2 := (A\1 -> A\2)\1;
_A := (A\1 -> A\2)(1 - 2)
L = 1
H = 1
M = 0
-1 = (L)



A : Type   B : Type
------------------
      A | B


C <: A || C <: B
----------------
  C <: A | B

A <: C    B <: C
----------------
  A | B <: C

Either A B =
  | (tag : "left", x : A)
  | (tag : "right", x : B);


(tag : "left", x : A) | (tag : "right", x : B) <: (tag : _A, x : _B);

(tag : "left", x : A) <: (tag : _A, x : _B); _A = "left" :: _B = tag | "left" => A;
(tag : "right", x : B) <: (tag : _A, x : _B); _A = "right" :: _B = tag | "right" => B;


(tag : "left" | "right", x : tag | "left" => A | "right" => B)

Bool =
  (H : Type) =>
  (A : Type) =>
  (B : Type) =>
  (K : Type) ->
  ((K_eq_A : H == A) => K) ->
  ((K_eq_B : H == B) => K) -> K;

true : A -> B -> Bool A A B = A => B => K => true => false => true (Refl A);
false : A -> B -> Bool B A B = A => B => K => true => false => false (Refl B);

Either A B =
  | (tag : true, x : A)
  | (tag : false, x : B);


(tag : Bool, x : Bool) | (tag : Int, x : Int);

(tag : Bool | Int, x : typeof tag | Bool => )

(H : Type, H_eq_Bool_or_Int : H == Bool | H == Int, tag : H, x : H)

f = (either : Either Int String) =>  (
  (tag, x) = either;
  ()
);

(A, x) => p

0 =>          1 => 2
x => (A : Type) => (x : \0)

a : (A : Type) -> _C@0 -> (A@2 -> A@3) -> _C@0\2;
b : (X : Type) -> _D@0 ->         _B@0 -> _B@0\1;

a : (A : Type) -> _C@0   -> (A@2 -> A@3) -> _C@0\2;
b : (X : Type) -> _C@0\0 ->         _B@0 -> _B@0\1;

a : (A : Type) -> _C@0   -> (A@2 -> A@3)   ->           _C@0\2;
b : (X : Type) -> _C@0\0 -> (A@2 -> A@3)\0 -> (A@2 -> A@3)\0\1;

// the fancy step
a : 0 : _C@0\2
b : 0 : (A@2 -> A@3)\0\1
a : 2 : _C@0
b : 0 : (A@2 -> A@3)\0\1
_C := (A@2 -> A@3)\0\1\(in_off - h_off)
_C := (A@2 -> A@3)\0\1\-2

// done
a : (A : Type) -> (A@2 -> A@3)\0\1\-2   -> (A@2 -> A@3)   -> (A@2 -> A@3)\0\1\-2\2;
b : (X : Type) -> (A@2 -> A@3)\0\1\-2\0 -> (A@2 -> A@3)\0 -> (A@2 -> A@3)\0\1;


// meta step, just solve the offsets
a : (A : Type) -> (A@2 -> A@3)\-1 -> (A@2 -> A@3)   -> (A@2 -> A@3)\1;
b : (X : Type) -> (A@2 -> A@3)\-1 -> (A@2 -> A@3)\0 -> (A@2 -> A@3)\1;

// meta step, just expand the types
a : (A : Type) -> (A@1 -> A@2) -> (A@2 -> A@3) -> (A@3 -> A@4);
b : (X : Type) -> (A@1 -> A@2) -> (A@2 -> A@3) -> (A@3 -> A@4);

// meta step, just fix the names
a : (A : Type) -> (A@1 -> A@2) -> (A@2 -> A@3) -> (A@3 -> A@4);
b : (X : Type) -> (X@1 -> X@2) -> (X@2 -> X@3) -> (X@3 -> X@4);

(f => (self => f (self self)) (self => f (self self))) id

(. (. \2 (\1 \1)) (. \2 (\1 \1))) (\. \1) : []
(. \2 (\1 \1)) (. \2 (\1 \1)) : (\. \1) :: []
\2 (\1 \1) : (. \2 (\1 \1)) :: (\. \1) :: []
(\. \1) ((. \2 (\1 \1)) (. \2 (\1 \1))) : (. \2 (\1 \1)) :: (\. \1) :: []
\1 : ((. \2 (\1 \1)) (. \2 (\1 \1))) :: (. \2 (\1 \1)) :: (\. \1) :: []
(. \2 (\1 \1)) (. \2 (\1 \1)) : ((. \2 (\1 \1)) (. \2 (\1 \1))) :: (. \2 (\1 \1)) :: (\. \1) :: []
\2 (\1 \1) : (. \2 (\1 \1)) :: ((. \2 (\1 \1)) (. \2 (\1 \1))) :: (. \2 (\1 \1)) :: (\. \1) :: []
((. \2 (\1 \1)) (. \2 (\1 \1))) ((. \2 (\1 \1)) (. \2 (\1 \1))) : (. \2 (\1 \1)) :: ((. \2 (\1 \1)) (. \2 (\1 \1))) :: (. \2 (\1 \1)) :: (\. \1) :: []
(. \2 (\1 \1)) (. \2 (\1 \1)) : ((. \2 (\1 \1)) (. \2 (\1 \1))) :: (. \2 (\1 \1))
(.\1z \1) (.\1 \1) : []
(\1 \1) : [1 -> (.\1 \1)]
(.\1 \1) (.\1 \1) : [1 -> (.\1 \1);]

(f => f f) (f => f f) : []
(f => f f) (f => f f) : [f -> f => f f]

(. \1 \2) : \2


{
  x : Int;
  x = 1;
}

M : {
  call_id : ((A : Type) -> A -> A) -> (x : Int, y : String);
} = {
  call_id = (id : (A : Type) -> A -> A) => x => id x;
  call_id = id => (x = id 1, id "a")
};

f : (p : (A : Type, x : A)) -> ((A, x) = p; A);
f = (p : (A : Type, x : A)) => (
  (A, x) = p;
  x
);

f : (A : Type, x : A) -> A;
f = (A : Type, x : A) => x;

((x : Type) => x\1) ((A : Type\1) -> A\1)
((x : Type\1) -> Type\2) Type\1
x\1[x\1 := ((A : Type) -> A\1)]

((x : Int) => e2) e1;

x = 1;
x

((A : Type\1) => (x : A\1) => x\1) Type\1

(A : Type\1) -> (x : A\1) -> A\2

((x : A\1) -> A\2)[A := Type\1]
((x : Type\1) -> A\2)[A := Type\1]

_A  -> _B
A\1 -> A\2

Type : ()
Type L : Type (L : 1)

Fix : (Fix : Type) & (fix : Fix) -> Unit;
Fix : (Fix : Type, f : (fix : Fix) -> Unit);

List :
  (A : Type) ->
  (L : Type) & (

    | (tag : "nil")
    | (tag : "cons", el : A, next : L)
  );

((A : Type) -> Int\2 -> A\2 -> A\3) Int\1;

((Int\2 -> A\2 -> A\3)\-1)[A := Int\1];
(Int\1 -> A\1 -> A\2)[A := Int\1];
(Int\1 -> Int\1\1 -> Int\1\2);
(Int\1 -> Int\2 -> Int\3);


l : (x : A) -> B   a : A
------------------------
  l a : ((x : A) => B) a

 l : (x : A) -> (y : B) -> C   a : A   b : B
----------------------------------------------
(l a) b : C\-1[x := a]\-1[y := B]

((A : Type\1) => A\1) Type\1

((A : Type) => A\1 -> A\2) String;


((A : Type\1) => (x : A\1) => x) : ((A : Type\1) -> (x : A\1) -> A\2)

(((A : Type\1) -> (x : A\1) -> A\2) Type\1)
((x : A\1) -> A\2); [A := Type\1]
((x : A\0) -> A\1); [A := Type\1]
((x : Type\1\0) -> Type\1\1); [A := Type\1]

(A : Type) => () => A;
(A : Type\1 : Type\0) => () => () => A; depth = 0;
(A : Type\1 : Type\1) => () => () => A; depth = 0; offset = 1;
(A : Type\1 : Type\1) => () => () => A; depth = 1;
(A : Type\1 : Type\1) => () => () => A; depth = 2;
(A : Type\1 : Type\1) => () => () => (A\3 : Type\1); depth = 3;
(A : Type\1 : Type\1) => () => () => (A\3 : Type\4); depth = 3; offset = 3;

is_bound_var = var <= depth;

(A : Type) => (x : A) => x;
(A : Type\1 : Type\0) => (x : A) => x; depth = 0;
(A : Type\1 : Type\1) => (x : A) => x; depth = 0; offset = 1;
(A : Type\1 : Type\1) => (x : A\1 : Type\2) => x; depth = 1;
(A : Type\1 : Type\1) => (x : A\1 : Type\2) => (x\1 : A\1); depth = 2;
(A : Type\1 : Type\1) => (x : A\1 : Type\2) => (x\1 : A\2); depth = 2; offset = 1;

+1

1 <= 0 = false
1 <= 1 = true
2 <= 1 = false
1 <= 2 = true
2 <= 2 = true

(A : Type\1 : Type\1) => (x : A\1 : Type\2) => (x\1 : A\2);

(A : Type\2 : Type\2) => (x : A\1 : Type\2) => (x\1 : A\2); depth = 0;
(A : Type\2 : Type\2) => (x : A\1 : Type\2) => (x\1 : A\2); depth = 0;
(A : Type\2 : Type\2) => (x : A\1 : Type\2) => (x\1 : A\2); depth = 1;

(A : Type\1 : Type\1) => () => () => (A\3 : Type\4); depth = 0;
(A : Type\1 : Type\2) => () => () => (A\3 : Type\4); depth = 0; depth < var
(A : Type\1 : Type\2) => () => () => (A\3 : Type\4); depth = 1;
(A : Type\1 : Type\2) => () => () => (A\3 : Type\4); depth = 2;
(A : Type\1 : Type\2) => () => () => (A\3 : Type\4); depth = 3;
(A : Type\1 : Type\2) => () => () => (A\3 : Type\5); depth = 3; 4 > depth

+1
(A : Type\1 : Type\1) => (A : Type\2); depth = 0;
(A : Type\1 : Type\1) => (A : Type\2); depth = 0;

Type\0 : Type\0
depth = 0; var = 1 - 1;

0 `bound` 0 = false
a `bound` a = false


var < depth

read : String -> Monad String;
debug : {A} -> A -> A;

Type : (l : Level) -> Type (l + 1);
Type 0 : Type 1;

(x : Int, y : Int) => x + y;
(p : (x : Int, y : Int)) => (
  (x, y) = p;
  x + y
);
((x = v; r) ((x => r) v);

((x : Int, y : Int) => x + y) (x = 1; y = 2);


(x : Int, y : Int) -> Int;

l : (x : A) -> B    a : A
-------------------------
  l a : B[x := A]

(x = 1, y = 1) (left => right => );


return = x => x;

add = (x, y) => (
  z = x + y;
  return z;
);

((x, y : Int) => x + y) == ((x : Int, y) => x + y);
((x, y : Int) => y) != ((x, y : String) => y)


(\x: IO () -> Int) (print "foobar")

Type =
  | Type
  | Forall (param : String) (annot : Type) (return : Type)
  | Lambda (param : String) (annot : Type) (return : Term)
  | Apply (lambda : Term) (arg : Term)
  | Inter (var : String) (left : Type) (right : Type)
  | Equal (a : Type) (b : Type);

Term =
  | Var (name : String)
  | Lambda (param : String) (annot : Type) (return : Term)
  | Apply (lambda : Term) (arg : Term);


-----------
Type : Type

 A : Type    B : Type
----------------------
((x : A) -> B) : Type

  A : Type  B : Type  e : B
-----------------------------
((x : A) => e) : (x : A) -> B


Id : Type = (A : Type) -> (x : A) -> A;
id : Id = (A : Type) => (x : A) => x;

Bool = (A : Type) -> (x : A) -> (y : A) -> A;
true = (A : Type) => (x : A) => (y : A) => x;
false = (A : Type) => (x : A) => (y : A) => y;

x : Int & String = _;
z : Int = x;


Connection : Resource = _;
send : (conn: Connection) -> (x : String) -> IO ((), Connection) = _;
close : (conn : Connection) -> IO () = _

alloc : (A : Resource) -> A;
free : (A : Resource) -> (x : A) -> ();

f = (conn0 : Connection) => (
  ((), conn1) = send(conn0, "Hello")?;
  ((), conn2) = send(conn1, "World")?;
  close conn2;
);

Induction

CNat : Type = X .-> X -> (X -> X) -> X;
cZ : CNat = X .=> z => s => z;
cS : CNat -> CNat = x => X .=> z => s => s (x X z s);

Inductive : CNat -> Type =
  (x : CNat) =>
  (P : CNat -> Type) .->
  P cZ -> ((y: CNat) .-> P y -> P (cS y)) ->
  P x;
iZ : Inductive cZ = P .=> z => s => z;
iS : (x : CNat) .-> Inductive x -> Inductive (cS x) =
  x .=> p => P .=> z => s => s x (p P z s)

Nat : Type = (x : CNat) & Inductive x;
Z : Nat = (x = cZ & iZ);
S : Nat -> Nat = n => (x = cS n.1, iS x n.2);




refl : {A} -> A == A = x => x;

C_bool = A. A -> A -> A;
c_true : C_bool = t => f => t;
c_false : C_bool = t => f => f;

Ind_bool : C_bool -> Type =
  b => (P : Bool). P c_true -> P c_false -> P b;
ind_true : Ind_bool c_true = t => f => t;
ind_false : Ind_bool c_false = t => f => f;

Bool : Type = (b : C_bool) & Ind_bool b;
true : Bool = (b = c_true & ind_true);
false : Bool = (b = c_false & ind_false);

ind_bool : (b : Bool) -> {P} -> P true -> P false -> P b =
  b => {P} => t => f =>
    @b.2
      (x => {X} -> ((m : Bool) -> x == m.1 -> P m -> X) -> X)
      ({X} => c => c true refl t)
      ({X} => c => c false refl f);
      (m => (e : b.1 == m.1) => (u : P m) =>
        e : b == m = e; // injective
        u[m := b | e]
      );

match_bool_with_eq :
  {A} -> (b : Bool) ->
  (t : (b == true) -> A) ->
  (f : (b == false) -> A) -> A =
  {A} => b =>
    @ind_bool b
      (m =>
        (t : (m == true) -> A) ->
        (f : (m == false) -> A) -> A)
      (t => f => t refl)
      (t => f => f refl);
simple_dependent_elimination = (tag : Bool) => (payload : tag Type Int String) => (
  @ind_bool tag
    (tag => (payload : tag Type Int String) -> String)
    (payload => Int.to_string payload)
    (payload => payload);
    payload
);

refl : {A} -> A == A = x => x;

C_bool = A. A -> A -> A;
Ind_bool : C_bool -> Type =
  b => P. P c_true -> P c_false -> P b;
Bool : Type = (b : C_bool) & Ind_bool b;
true : Bool = t => f => t;
false : Bool = t => f => f;

(b : Bool) -> {P} -> P true -> P false -> P b

C_eq = A. A -> A;
c_refl : C_eq = x => x
Ind_eq : C_eq -> Type =
  eq => P. P c_refl -> P eq;
ind_refl : Ind_eq c_refl = x => x;

Eq = (eq : C_eq) & Ind_eq eq;
refl = (eq = c_refl) & ind_refl;

ind_bool : (b : Bool) -> {P} -> P true -> P false -> P b =
  b => {P} => t => f => (
    (m : Bool, x_eq_m_1 : b == m.1, p_m : P m) =
      @b.2 (true, refl, t) (false refl f);
    e : b == m = e; // injective
    u[m := b | e]
  );


Eq = {
  &A : Type;
  eq : (x : A) -> (y : A) -> x == y;
};

( == ) :
  (( == ) : {A} -> (x : A) -> (y : A) -> Type) &
  (( == ) : {A : Eq} -> (x : A) -> (y : A) -> x == y);

( == ) =
  A. (x : A) => (y : A) => R.
    {r_either_type_or_eq :
      Either
        (R == Type)
        (_ : R == Option (x == y), cmp : (x : A) -> (y : A) -> Option (x == y))
    } => (
      r_either_type_or_eq
      | ("left", r_eq_type) => (x == y : R)
      | ("right", (r_eq_opt_x_eq_y, cmp) => (cmp x y : R))
    );

x : R.
    {r_either_type_or_eq :
      Either
        (R == Type)
        (_ : R == Option (x == y), cmp : (x : A) -> (y : A) -> Option (x == y))
    } -> R = 1 == 1;
f : A. (x : A) -> (y : A) ->
    {r_either_type_or_eq :
      Either
        (Type == Type)
        (_ : Type == Option (x == y), cmp : (x : A) -> (y : A) -> Option (x == y))
    } -> Type;

True = (A : Type) -> A -> A;
False = (A : Type) -> A;

C_bool = A. A -> A -> A;
c_true : C_bool = t => f => t;
c_false : C_bool = t => f => f;

Ind_bool : C_bool -> Type =
  b => (P : Bool). P c_true -> P c_false -> P b;
ind_true : Ind_bool c_true = t => f => t;
ind_false : Ind_bool c_false = t => f => f;

Bool : Type = (b : C_bool) & Ind_bool b;
true : Bool = (b = c_true & ind_true);
false : Bool = (b = c_false & ind_false);

f : ((x : Int) -> Int) & ((x : String) -> String) = x => x;
ind_bool : (b : Bool) -> {P} -> P true -> P false -> P b = _;
ind_eq : A. (x : A) -> (y : A) -> (eq : Eq x y) -> P. P x -> P y = _;

f = (eq : true == false) : False => (
  t : (b =>
    ind_bool b
      (_ => Type)
      True
      False
  ) true = x => x;
  f : (b =>
    ind_bool false
      (_ => Type)
      True
      False
  ) false = (t : _[true := false | eq]);
  f
);

Either A B =
  (left : Bool, payload : left A B);

match_bool_with_eq :
  {A} -> (b : Bool) ->
  (t : (b == true) -> A) ->
  (f : (b == false) -> A) -> A =
  {A} => b =>
    @ind_bool b
      (m =>
        (t : (m == true) -> A) ->
        (f : (m == false) -> A) -> A)
      (t => f => t refl)
      (t => f => f refl);
f = (x : Either Int String) => (
  (left, payload : left Int String) = x;
  match_bool_with_eq left
    (left_eq_true => Int.to_string (payload : _[left := true | left_eq_true]))
    (left_eq_false => (payload : _[left := false | left_eq_false]))
);

make : (x : Nat) -> (x_gt_z : x >= 0) -> _ = _

make : (x : Nat, {x >= 0}) -> _ = _

Either A B =
  | (tag : "left", payload : A)
  | (tag : "right", payload : B);


'A = (
  f = (x : 'A) => x;
  x : 'A = 1;
  int
)

Holes

a : (A : Type) -> _C -> (A\2 -> A\2) -> _C\2
b : (X : Type) -> _D ->           _B -> _B\1

a : (A : Type) -> _C -> (A\2 -> A\2) -> _C\2
b : (X : Type) -> _C ->           _B -> _B\1

a : (A : Type) -> _C -> (A\2 -> A\2) -> _C\2
b : (X : Type) -> _C -> (A\2 -> A\2) -> (A\2 -> A\2)\1

a : (A : Type) -> _C -> (A\2 -> A\2) -> _C\2
b : (X : Type) -> _C -> (A\2 -> A\2) -> (A\2 -> A\2)\1

a : 0 : _C\2
b : 0 : (A\2 -> A\2)\1

a : 2 : _C
b : 1 : (A\2 -> A\2)

_C := (A\2 -> A\2)\-1;

a : (A : Type) -> (A\2 -> A\2)\-1 -> (A\2 -> A\2) -> (A\2 -> A\2)\-1\2
b : (X : Type) -> (A\2 -> A\2)\-1 -> (A\2 -> A\2) -> (A\2 -> A\2)\1

a : _A ->         _A\1 -> _B
b : _C -> (_D -> _D\1) -> _D\1

a : _A ->         _A\1 -> _B
b : _A -> (_D -> _D\1) -> _D\1

a : _A\1
b : (_D -> _D\1)

a : 1 : _A
b : 0 : (_D -> _D\1)

1 - 0
0 < 1
_D := _E\1
_A := (_E\1 -> _E\1\1)\-1

a : (_E\1 -> _E\1\1)\-1 -> (_E\1 -> _E\1\1)\-1\1 -> _B
b : (_E\1 -> _E\1\1)\-1 -> (_E\1 -> _E\1\1) -> _E\1\1

a : (_E -> _E\1) -> (_E\1 -> _E\2) -> _E\2
b : (_E -> _E\1) -> (_E\1 -> _E\2) -> _E\2

Induction and Literals

(Bool, true, false, ind_bool) = (
  Bool = A. A -> A -> A;
  true : Bool = t => f => t;
  false : Bool = t => f => f;

  Bool = (b : Bool) & (P. P true -> P false -> P b);
  true : Bool = t => f => t;
  false : Bool = t => f => t;

  ind_bool : (b : Bool) -> P -> P true -> P false -> P b =
    b => P => p_t => p_f => (
      (m, b_eq_m, p_m) =
        b
          (x => (m : Bool, x_eq_m1 : x == m, p_m : P m))
          (true, refl, p_t)
          (false, refl, p_t);
      (p_m : _[m := b | b_eq_m]);
  );

  (Bool, true, false, ind_bool);
);

Either A B =
  | (tag = true, payload : A)
  | (tag = false, payload : B);

(tag = true, payload : A) <: (tag : Bool, payload : tag A B)
(tag = false, payload : B) <: (tag : Bool, payload : tag A B)

f = (x : Either Int String) => (
  (tag, payload : tag Int String) = x;
  ind_bool
    ((payload : Int) => Int.to_string payload)
    ((payload : String) => payload)
    payload
);

expected : (tag : Bool, payload : tag Type A Never);
received : (tag : Bool & tag == true, payload : A);

expected : Bool
received : (tag : Bool & tag == true)

f = (x : Either Int String) => (
  x : (tag : Bool, payload : tag Type A B) = x;
  (tag, payload : tag Type A B) = x;
  ()
);

a : (a : Int, b : Int) -> a == b
b : (a : _) -> _
((p : (a : Int, b : Int)) -> ((a : Int, b : Int) => a == b) p);

x => x

a : F (a = Int, b = String) -> ((a : Type, b : Type) => a) _B -> Int;
b : F (_A : _)                    -> ((a : Type, b : Type) => a) _A -> Int;

a : (a : Int, b : Int) => a;
b : (_x : _A) => _b;

a : ((a, b) : (a : Int, b : Int)) => a
b : (_x : _B) => _b;


x = (p : (a : Int, b : Int)) -> ((a : Int, b : Int) => a == b);
a : (a : Int, b : Int) => a;
b : (x : _A) => _b;


C_bool = (A : Type) -> A -> A -> A;
c_true : Bool = A => t => f => t;
c_false : Bool = A => t => f => f;

Ind_bool b = (P : Bool -> Type) -> P c_true -> P c_false -> P b;
Bool = (b : Bool & Ind_bool b);
true : Bool = X => t => f => t;
false : Bool = X => t => f => t;
ind_bool : (b : Bool) -> P -> P true -> P false -> P b =
  b => P => p_t => p_f => (
    (m, b1_eq_m1, p_m) =
      b.2
        (x => (m : Bool, x_eq_m1 : x == m.1, p_m : P m))
        (true, refl, p_t)
        (false, refl, p_t);
    b_eq_m : b == m = b1_e1_m1;
    (p_m : _[m := b | b_eq_m]);
);
(t => f => t) : A. A -> A -> A;

expected : (P : Bool -> Type) -> P true -> P false -> P b;
received : (A : Type)         -> A      ->       A ->   A;

Row Polymorphism

pure : A. A -> IO A;
bind : A. B. (A -> B) -> IO A -> IO B;

handle : (A. Effect A -> A) -> K. (() -> Effect K) -> K

or = Read A;

Read | Write
read : E. () -> Read `or` E $-> String;
write : E. () -> Write `or` E $-> String;

And : (A : Type) -> (B : Type) -> Type;

Level : Type¹
f = (x : Nat `And` x == 1)

f : () -> (A => Read A | Write A) String;

Hurkens Universe Polymorphic

⊥ = (A: *) -> A;
¬ φ === φ -> ⊥;S === (L : Level) -> S -> Type L;

U : Type 1 = (L : Level) -> (X : Type L) -> (℘℘X -> X) -> ℘℘X;
τ (t: ℘℘U) = (L : Level) => (X : Type L) => (f : ℘℘X -> X) => (p : ℘X) =>
  t L (L2 => (x : U) => p L2 (f (x L X f)));
σ (s: U) : ℘℘U = s 1 U τ;
∆ = (y: U) => (p: ℘U) -> σ y p -> p (τ (σ y));: U = τ ((p: ℘U) => (x: U) -> σ x p -> p x);S === (L : Level) -> S -> Type L;
U : Type 1 = (L : Level) -> (X : Type L) -> (℘℘X -> X) -> ℘℘X;

τ : ((L : Level) -> ℘U -> Type L) -> U;
σ : U -> ((L : Level) -> ℘U -> Type L);: U = τ (L => (p: ℘U) => (x: U) -> σ x L p -> p L x);

Effects

Id = (A : Type) -> (x : A) -> A;
id = (A : Type) => (x : A) => x;

Bool = (A : Type) -> (t : A) -> (f : A) -> A;
true : Bool = A => t => f => t;
false : Bool = A => t => f => f;
ind_bool : b => (P : Bool -> Type) -> P true -> P false -> P b = _;
match_bool_with_eq :
  {A} -> (b : Bool) ->
  (t : (b == true) -> A) ->
  (f : (b == false) -> A) -> A = _;

Compare = {A} -> (x : A) -> (y : X) -> Either (x == y) (x <> y);

Either A B = (tag : Bool, payload : tag Type A B);
f = (x : Either Int String) =>
  x
  | (tag = true, payload) => Int.to_string payload
  | (tag = false, payload) => payload;

Normalization

Term =
  | x
  | (x : Term) -> Term
  | (x : Term) => Term
  | Term Term
  | (a : Term, b : Term)
  | (a = Term, b = Term)
  | (x, y) = Term; Term

norm
  | <x> => <x>
  | <(p : A) -> r> => norm_forall <(p : A) -> r>
  | <(p : A) => r> => norm_lambda <(p : A) => r>
  | <lambda arg> => norm_apply <lambda arg>;


norm_forall =
  | <(x : A) -> B> =>
    A = norm A;
    B = norm B;
    <(x : A) -> B>
  | <(p : A) -> B> =>
    norm <(x : A) -> ((p : A) => B) x>;

norm_lambda =
  | <(x : T) => r> =>
    T = norm T;
    r = norm r;
    <(x : T) => r>
  | <(x : A, y : B) => r> =>
    A = norm A;
    B = norm B;
    r = norm r;
    <(x : A, y : B) => r>
  | <(p1 : A, p2 : B) => r> =>
    norm <
      (z : (p1 : A, p2 : B)) =>
        (x : A, y : B) = z;
        (p1 : A) = x;
        (p2 : B) = y;
        r
    >;

norm_apply1
  | <lambda arg> =
    // TODO: norm head?
    lambda = norm lambda;
    arg = norm arg;
    norm_apply2 <lambda arg>;

norm_apply2
  // apply
  | <((x : A) => r) arg> =>
    norm (r[x := arg])
  // fst
  | <((x : A, y : B) => x) (x = arg_x, y = _)> =>
    <arg_x>
  // snd
  | <((x : A, y : B) => y) (x = _, y = arg_y)> =>
    <arg_y>
  // unpair
  | <((x : A, y : B) => r) arg> =>
    arg_x = <((x : A, y : B) => x) arg>;
    arg_y = <((x : A, y : B) => y) arg>;
    norm (r[x := arg_x][y := arg_y])
  // normal
  | <lambda arg> => <lambda arg>

norm_exists =
  | <(p : A, _ : B)> =>
    A = norm A;
    B = norm <((p : A) => B) x>;
    <(x : A, _ : B)>;

f = (
  (a : Int, b : Int) = a_b;
  (c_d : (c : Int, d : a == c)) => (
    (c : Int, d : a == c) = c_d;
    a + b + c
  )
) (c = 1, d = d);


f = (
  (a : Int, b : Int) = a_b;
  (c_d : (c : Int, d : a == c)) => (
    (c : Int, d : a == c) = c_d;
    a + b + c
  )
) (c = 1, d = d);

f = (
  (a : Int, b : Int) = a_b;
  (c_d : (c : Int, d : a == c)) => (
    (c : Int, d : a == c) = c_d;
    a + b + c
  )
) (c = 1, d = d);

f = (
  (a : Int, b : Int) = a_b;
  (c_d : (c : Int, d : a == c)) => (
    (c : Int, d : a == c) = c_d;
    a + b + c
  )
) (c = 1, d = d);

f = (
  (a : Int, b : Int) = a_b;
  (c : Int, d : a == c) = c_d;
  a + b + c
)[c_d := (c = 1, d = d)];

Either A B =
  | (tag = "left", payload : A)
  | (tag = "right", payload : B);

f = (x : Either Int String) =>
  [%match x
  | (tag = "left", payload) => Int.to_string payload
  | (tag = "right", payload) => payload];

f = ((a : Int, b : Int), (c : Int, d : a == c)) => a + b + c;
f = (a_b_c_d : (a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c))) => (
  (a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c)) = a_b_c_d;
  (a : Int, b : Int) = a_b;
  (c : Int, d : a == c) = c_d;
  a + b + c
);
f = (a_b_c_d : (a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c))) =>
  ((a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c)) => (
    (a : Int, b : Int) = a_b;
    (c : Int, d : a == c) = c_d;
    a + b + c
  )) a_b_c_d;
f = (a_b_c_d : (a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c))) =>
  ((a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c)) => (
    ((a : Int, b : Int) => (
      (c : Int, d : a == c) = c_d;
      a + b + c
    )) a_b
  )) a_b_c_d;

f =
  (a_b_c_d : (a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c))) =>
    ((a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c)) =>
      ((a : Int, b : Int) => ((c : Int, d : a == c) => a + b + c) c_d) a_b) a_b_c_d;

f = ((a : Int, b : Int) => (c : Int, d : a == c) => a + b + c) a_b (c = 1; d = d);
f = ((a : Int, b : Int) => a + b + 1) a_b

f =
  ((a : Int, b : Int) =>
    (c_d : (c : Int, d : a == c)) =>
      ((c : Int, d : a == c) => a + b + c) c_d) a_b (c = 1; d = d);
f = (
  (a : Int, b : Int) = a_b;
  (c_d : (c : Int, d : a == c)) => (
    (c : Int, d : a == c) = c_d;
    a + b + c
  )
) (c = 1; d = d);

f = (
  (a : Int, b : Int) = a_b;
  (c_d : (c : Int, d : a == c)) => (
    (c : Int, d : a == c) = c_d;
    a + b + c
  )
) (c = 1; d = d);

f = (
  (a : Int, b : Int) = a_b;
  a + b + 1
);

f =
  ((a : Int, b : Int) => (c_d : (c : Int, d : a == c)) =>
    ((c : Int, d : a == c) => a + b + c) c_d); a_b :: (c = 1; d = d) :: []

f =
  ((a : Int, b : Int) =>
    ((c : Int, d : a == c) => a + b + c) (c = 1; d = d)); []

f = ((a : Int, b : Int) => a + b + 1) a_b;
E = (a : Int, (b, c) : (b : Int, c : Int));
E = (a : Int, b_c : (b : Int, c : Int));

E = ((a, b) : (a : Int, b : Int), a_eq_b : a == b);
E = (a_b : (a : Int, b : Int), a_eq_b : ((a : Int, b : Int) => a == b) a_b);


f = (a : Int, b : Int) => a == b;
f = (a_b : (a : Int, b : Int)) => ((a : Int, b : Int) => a == b) a_b;

f = (a : Int, b : Int) -> a == b;
f = (a_b : (a : Int, b : Int)) -> ((a : Int, b : Int) => a == b) a_b;

f = (a_b : (a : Int, b : Int)) -> ((a : Int, b : Int) => a == b) a_b;
f = (a_b : (a : Int, b : Int)) -> ((a : Int, b : Int) => a == b) a_b;

f = (((a : Int, b : Int), c : Int) => a + b + c) (a_b = a_b, c = 1);

f = (((a : Int, b : Int), c : Int) => a + b + c) (a_b = a_b, c = 1);
f = (((a : Int, b : Int), c : Int) => ((a : Int, b : Int) => a + b + c) a_b) (a_b = a_b, c = 1);
f = (((a : Int, b : Int) => a + b + 1) a_b);

f = ((a : Int, b : Int), (c : Int, d : a == c)) => a + b + c;
f = ((a : Int, b : Int), (c : Int, d : a == c)) => a + b + c;

f =
  ((a : Int, b : Int), c_d : (c : Int, d : a == c)) =>
    ((c : Int, d : a == c) => a + b + c) c_d;
f =
  (a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c)) =>
    ((a : Int, b : Int) => ((c : Int, d : a == c) => a + b + c) c_d) a_b;

f =
  (a_b_c_d : (a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c))) =>
    ((a_b : (a : Int, b : Int), c_d : (c : Int, d : a == c)) =>
      ((a : Int, b : Int) => ((c : Int, d : a == c) => a + b + c) c_d) a_b) a_b_c_d

f =
  (a_b_c : (a_b : (a : Int, b : Int), c : Int)) =>
    ((a_b : (a : Int, b : Int), c : Int) =>
      ((a : Int, b : Int) => a + b + c) a_b) a_b_c;

f = (a_b : (a : Int, b : Int)) => f a_b;
f = (a : Int, b : Int) => f (a = a, b = b);

f = (a_b : (a : Int, b : Int)) =>
  ((a : Int, b : Int) => f (a = a, b = b)) a_b;

f = (a_b_c : ((a : Int, b : Int), c : Int)) => (((a : Int, b : Int), c : Int) => a + b + c) a_b_c;
f = (a_b_c : ((a : Int, b : Int), c : Int)) => (((a : Int, b : Int), c : Int) => a + b + c) a_b_c;


f = (((a : Int, b : Int), c : Int) => a + b + c) (a_b = a_b, c = 1);
f = ((a : Int, b : Int) => a + b + 1) a_b);

f = (a : Int, b : Int) => ();
f = (a_b : (a : Int, b : Int)) => ();
f = (a_b : (a : Int, b : Int)) => ();

Quantitative / Graded

id : (A : 0 : Type) -> (x : 1 : A) -> A;
id = (A : 0 : Type) => (x : 1 : A) => x;

double = (x : 2 : Int) => x + x;


with_x : ((x : 1 : Int) -> Int) -> Int;

// fails
x = with_x (x => double x);

Forget + Intersection

(Bool, true, false, ind_bool) = (
  Bool = A. A -> A -> A;
  true : Bool = t => f => t;
  false : Bool = t => f => f;

  Bool = (b : Bool) & (P. P true -> P false -> P b);
  true : Bool = t => f => t;
  false : Bool = t => f => t;

  ind_bool : (b : Bool) -> P -> P true -> P false -> P b =
    b => P => p_t => p_f => (
      (m, b_eq_m, p_m) =
        b
          (x => (m : Bool, x_eq_m1 : x == m, p_m : P m))
          (true, refl, p_t)
          (false, refl, p_t);
      (p_m : _[m := b | b_eq_m]);
  );

  (Bool, true, false, ind_bool);
);

Either A B =
  | (tag = true, payload : A)
  | (tag = false, payload : B);

f = (x : Either Int String) => (
  (tag : Bool, payload : tag Type Int String) = x;
  payload
);

F = (x : Either Int String) ->
  ((tag : Bool, payload : tag Type Int String) -> payload) x
f = (x : Either Int String) =>
  ((tag : Bool, payload : tag Type Int String) => payload) x
f = (x : Either Int String) => (
  (tag : Bool, payload : tag Type Int String) = x;
  payload
);


f = (x : Int) => (
  x
  | (tag = true, payload) => Int.to_string payload
  | (tag = false, payload) => payload
);

id = (L : Level) => (A : Type L) => (x : A) => x;

f = (b : Bool & b == true);

with_linear_int : (cb : (x : 1 : Int) -> Int) -> Int = _;
x = with_linear_int (x => x + x);

id = (A : 0 : Type) => (x : A) => x;
rewrite =
  (A : Type) => (B : Type) =>
  (x_eq_y : 0 : A == B) =>
  (x : 1 : A) => (x : A[A := B | x_eq_y]);

Map Key Value : {
  find : (key : Key) -> (map : @Map) -> Value;
  find_and_remove : (key : Key) -> (map : @Map) -> (Value, @Map);
} = _;

IUP + Induction

// Church booleans
C_bool : Type 1 = (L : Level) -> (A : Type L) -> A -> A -> A;
c_true : Bool = L => A => t => f => t;
c_false : Bool = L => A => t => f => f;

// Induction principle
I_bool = b : Type 1 => (L : Level) -> (P : C_bool -> Type L) -> P c_true -> P c_false -> P b;
// Without IUP, Bool would be placed on Type Omega, making it useless
Bool : Type 1 = (b : Bool) & (ind : I_bool b);
true : Bool = L => X => t => f => t;
false : Bool = L => X => t => f => t;

ind_bool : (b : Bool) -> (L : Level) -> (P : Bool -> Type L) -> P true -> P false -> P b =
  b => L => P => p_t => p_f => (
    (m, b1_eq_m1, p_m) =
      b.2
        L
        (x => (m : Bool, x_eq_m1 : x == m.1, p_m : P m))
        (c_true, refl, p_t)
        (c_false, refl, p_f);
    // b.1 == m.1 implies in b == m
    b_eq_m : b == m = b1_eq_m1;
    // use b == m to change P m into P b
    (p_m : _[m := b | b_eq_m]);
);

C_sigma = (A : Type) => (B : A -> Type) =>
  (K : Type) -> ((x : A) -> (y : B x) -> K) -> K;
c_exist = A => B => x => y : C_sigma A B => K => f => f x y;

I_sigma = (A : Type) => (B : A -> Type) => s =>
  (P : C_sigma A B -> Type) ->
  ((x : A) -> (b : B x) -> P (c_exist A B x y)) ->
  P s;
Sigma = A => B => (s : C_sigma A B) & (ind : I_sigma s);

exist = A => B => x => y : Sigma A B => X => f => f x y;

ind_sigma = A => B => x => y => s => (P : Sigma A B -> Type) => (p_e : P (exist A B x y)) =
  (m, s1_eq_m1) =
    s.2
      (x => (m : Sigma, x_eq_m1 : x == m.1, p_m : P m))
      (x => y => (exist A B x y, refl, p_e));

C_sigma = (L : Level) => (A : Type L) => (B : A -> Type L) =>
  (K_L : Level) -> (K : Type K_L) -> ((x : A) -> (y : B x) -> K) -> K;
c_exist = L => A => B => x => y : C_sigma A B => K_L => K => f => f x y;

Exists : Type 2 = ((K_L : Level) -> (K : Type K_L) -> ((x : Type 1) -> (y : x) -> K) -> K);
x = c_exist 1 Type (A => A) Nat 1;

I_sigma = (A : Type) => (B : A -> Type) => s =>
  (P : C_sigma A B -> Type) ->
  ((x : A) -> (b : B x) -> P (c_exist A B x y)) ->
  P s;
Sigma = A => B => (s : C_sigma A B) & (ind : I_sigma s);
exist = A => B => x => y : Sigma A B => X => f => f x y;


C_sigma = (A : Type) => (B : A -> Type) =>
  (K : Type) -> ((x : A) -> (y : B x) -> K) -> K;
c_exist = A => B => x => y : C_sigma A B => K => f => f x y;

I_sigma = (A : Type) => (B : A -> Type) => s =>
  (P : C_sigma A B -> Type) ->
  ((x : A) -> (b : B x) -> P (c_exist A B x y)) ->
  P s;
Sigma = A => B => (s : C_sigma A B) & (ind : I_sigma s);
exist = A => B => x => y : Sigma A B => X => f => f x y;

Core

C_bool : Type 1 = (A : Type L) -> A -> A -> A;
c_true : Bool = A => t => f => t;
c_false : Bool = A => t => f => f;

// Induction principle
I_bool = b => (P : C_bool -> Type) -> P c_true -> P c_false -> P b;
// Without IUP, Bool would be placed on Type Omega, making it useless
Bool : Type 1 = (b : Bool) & (ind : I_bool b);
true : Bool = L => X => t => f => t;
false : Bool = L => X => t => f => t;

t : (x : A) & B;
t.2 : B[x := t.1]

Equal : (A : Type) -> (x : A) -> (y : A) -> Type;
refl : (A : Type) -> (x : A) -> Equal A x x;
subst :
  (A : Type) ->
  (x : A) ->
  (y : A) ->
  (x_eq_y : x == y) ->
  (P : A -> Type) ->
  P x ->
  P y;
symm = A => (x : A) => y => (x_eq_y : x == y) =>
  subst A x y x_eq_y
    (n => n == x)
    (refl A x);

More IUP

((X : _) => (x : _) => x) : (A : Type) -> (x : A) -> A;

(b : (A : Type) -> A -> A -> A) &
  ((P : ((A : Type) -> A -> A -> A) -> Type) -> (P ((A\1 : Type) => (t : A) => (f : A) => t)) ->  (P ((A\2 : Type) => (t\1 : A) => (f\1 : A) => f)) -> P b)

id = (x : _A) => x;

expected :: (A : Type) -> (x : A) -> A;
received :: (X : Type) -> (y : X) -> X;

expected :: (A : \1) -> (x : \1) -> \2;
received :: (X : \1) -> (y : \1) -> \1;

with_context : {A} -> ({K} -> Context -> (A -> K) -> K) -> _;
with_offset : Side -> Offset.t -> (() -> T 'A) -> T 'A

norm 0 [] <((A : Type\1) => (x : A\1) => (y : A\2) => (x\2 : A\3)) Type\1>;
norm -1 [A := Type\1] <(x : A\1) => (y : A\2) => (x\2 : A\3)>;
norm -1 [A := Type\1] <(x : A\1) => (y : A\2) => (x\2 : A\3)>;

((x : A\1) => x\1)\-1[A := Type\1]

((x : A\1) => x\1)\-1[A := Type\1]

((x : A\1) => x\1)\-1[A := Type\1]

l : (x : A) -> B    a : A
-------------------------
  l a : ((x : A) => B) a

l : (x : A) -> B    a : A
-------------------------
  l a : B[x := a]

Unification

a : (A : Type) -> _C -> (A\2 -> A\3) -> _C\2
b : (X : Type) -> _D ->           _B -> _B\1

a : (A : Type) -> _C -> (A\2 -> A\3) -> _C\2
b : (X : Type) -> _C ->           _B -> _B\1

a : (A : Type) -> _C -> (A\2 -> A\3) -> _C\2
b : (X : Type) -> _C -> (A\2 -> A\3) -> (A\2 -> A\3)\1

a : (A : Type) -> _C -> (A\2 -> A\3) -> _C\2
b : (X : Type) -> _C -> (A\2 -> A\3) -> (A\2 -> A\3)\1

a : 2 : _C\2
b : 1 : (A\2 -> A\3)

_C := (A\2 -> A\3)\-1

a : 0 : [] : (A : Type) -> ((B : Type) -> (A\1 -> B\1)\2)\-1 = (A : Type) -> (B : Type) -> A\2 -> B\2
  a : -1 : [Bound] : (B : Type) -> (A\1 -> B\1)\2 = (B : Type) -> A\2 -> B\2
    a : 1 : [Bound, Bound] : A\1 -> B\1 = A\2 -> B\2
      a : 1 : [Bound, Bound] : A\1 = A\2
      a : 1 : [Bound, Bound] : B\1 = B\2


(e : A) === (((x : A) => x) e) === e

succ : Nat -> Nat = _;
(((x : Int) => succ x) 0);
succ (((x : Int) => x) 0);

(L : Level) -> (T : Type L, x : T)

(A : Type) -> A

(A : Type) -> (x : A) -> A
(A : Type\1) ->

norm [Bound, Bound] ((x : A\1) -> (A\2 : Type\3))

Syntax

x = ((A : Type) => A : (A : Type) -> )

(\1 -> \1)+1~

(A -> A)\[a.te:0:1 .. a.te:1:2]

index
#+-offset
#[a.te:0:1 .. a.te:1:2]


(A : Type) => (A : Type) => (x : A\1) => x;


add = (a, b) => a + b;
(x : Bool) = 1;

((id : (A : \1 : (\1 : \1)) -> (x : \1 : (\1 : (\2 : \2)) -> (\2 : (\1 : (\1 : \1))#+2)) => (\1 : ((A : \1 : (\1 : \1)) -> (x : \1 : (\1 : (\2 : \2)) -> (\2 : (\1 : (\1 : \1))#+2))#+1)) ((A : \1) => (x : \1) => (\1 : \1#+1))

Eta Sigma?

C_sigma A B = (K : Type) -> ((l : A) -> (r : B l) -> K) -> K;
c_pair A l B r : C_sigma A B = K => f => f l r;


Sigma = A => (x : A) => B => (y : B x) => (

);

f = (
  (a : Int, b : Int) = a_b;
  (c_d : (c : Int, d : a == c)) => (
    (c : Int, d : a == c) = c_d;
    a + b + c
  )
) (c = 1, d = d);

Weak Intersections

C_bool = (A : Type) -> A -> A -> A;
c_true : C_bool = A => t => f => t;
c_false : C_bool = A => t => f => f;

Ind_bool = b => (P : C_bool -> Type) -> P c_true -> P c_false -> P b;

Bool = (b : C_bool) & Ind_bool b;

Bool = (b !: C_bool & ind : Ind_bool b)

ind_true : I_bool c_true = P => p_c_t => p_c_f => p_c_t;
ind_false : I_bool c_false = P => p_c_t => p_c_f => p_c_f;

Never = (A : Type) -> A;
rec%Fix = (self : Fix) -> Never;


Bool = rec%self. (
  c : C_bool,
  ind : Ind_bool c,
  inj : 0 : (x : Bool) -> fst self == fst x -> self == x
);
true = rec%self. (c = c_true, ind = i_true, inj = y => fst_self_eq_fst_y => (
  (_, _, x_inj) = x;
  y_eq_self : fst y == fst self -> y == self) = x = y_inj self (symm fst_self_eq_fst_y);
  symm y_eq_self;
));


fst a == fst b -> a == b

true : Bool = _;
false : Bool = _;
ind_bool = b => P => p_t => p_f => (
  (x : Bool, c_b_eq_c_x : fst b == fst x, p_x : P x) =
    (snd b) _ (true, refl, p_t) (false, refl, p_f);

)

Leibniz Equality

Term =
  | Var (String)
  | Lambda (String, Term, Term)
  | Apply (Term, Term)
  | Type
  | Forall (String, Term, Term)
  | Mu (String, Term);

( == ) = A => (x : 0 : A) => (y : 0 : A) => (P : A -> Type) -> P x -> P y;
(refl : (A : Type) -> (x : 0 : A) -> x == x) =
  A => x => P => p_x => p_x;
(symm : (A : Type) -> (x : 0 : A) -> (y : 0 : A) -> x == y -> y = x) =
  A => x => y => x_eq_y => x_eq_y (z => z == x) (refl A x);

C_bool = (A : Type) -> A -> A -> A;
(c_true : C_bool) = A => t => f => t;
(c_false : C_bool) = A => t => f => f;

Ind_bool b = (P : C_bool -> Type) -> P c_true -> P c_false -> P b;


Y : (A : Type) -> (A -> A) -> A = f => (
  fix = (x : @S. S -> A) => f (x x);
  fix fix
);

Nat = @Nat. (A : Type) -> (zero : A) -> (succ : Nat -> A) -> A;

Pair A B = (K : Type) -> ((l : A) -> (r : B l) -> K) -> K;
pair A x B y : Pair A B = K => f x y;
fst A B (pair : Pair A B) = pair A (l => r => l);
snd A B (pair : Pair A B) = pair (B (fst A B pair)) (l => r => r);

rec%(Bool : Type) = Pair C_bool (comp => (
  ind : Ind_bool b,
  rel : (x : Bool) -> self.comp == x.c -> self == x
));

P_bool Rel = (comp : C_bool, rel : Rel);
X = rec @@ Rel =>
  (x : P_bool Rel) ->
  fst comp == fst x ->

Pair C_bool
(Rel : C_bool -> Type) =>
  (K : Type) -> (
    (comp : C_bool) ->
    (ind : Ind_bool comp) ->
    (rel : rec Rel @@
      (x : Bool) ->
        comp == (x C_bool (comp => _ => _ => comp)) -> self == x
      ) -> K)
    -> K;
Rel = (comp : C_bool) =>


P_bool (Rel : C_bool -> Type) =
  (K : Type) -> ((comp : C_bool) -> Ind_bool comp -> Rel comp -> K) -> K;
Make_rel = (Rel : C_bool -> Type) => (self : P_bool Rel) => (comp : C_bool) =>
  (x : P_bool Rel) -> comp == (x C_bool (comp => _ => _ => comp)) -> self == x;


rec%(Bool : Type) = (
  comp : C_bool,
  ind : Ind_bool b,
  rel : (x : Bool) -> self.comp == x.c -> self == x
);
rec%(self : Bool) => {
  b : C_bool;
  i : Ind_bool b;
  p : (x : 1 : Bool) -> self.c == x.c -> self == x;
};
rec%(true : Bool) = {
  b = c_true;
  i = P => p_t => p_f => p_t;
  p = x => true_c_eq_x_c => (
    x_c_eq_true_c = symm A true.c x.c true_c_eq_x_c;
    x_eq_true = x.p true x_c_eq_true_c;
    symm A x true x_eq_true
  );
};

rec%(Bool : Type) = rec%(self : Bool) => {
  b : C_bool;
  i : Ind_bool b;
  p : 0 : (x : Bool) -> self.c == x.c -> self == x;
};

rec%(Fix : Type) = (self : Fix) -> (A : Type) -> A;


f = (1 : (
  fix : Fix = fix => fix fix;
  magic : (A : Type) -> A = fix fix;
));

Safe

// computing
C_bool B T F (S : B) = (A : Type) -> (S == T -> A) -> (S == F -> A) -> A;

(c_true : C_bool) = A => t => f => t;
(c_false : C_bool) = A => t => f => f;

// computing
C_bool = (A : Type) -> A -> A -> A;
(c_true : C_bool) = A => t => f => t;
(c_false : C_bool) = A => t => f => f;

// induction
I_bool b = (P : C_bool -> Type) -> P c_true -> P c_false -> P b;
i_true : I_bool c_true = P => p_t => p_f => p_t;
i_false : I_bool c_false = P => p_t => p_f => p_f;

// template
T_bool Rel = {
  comp : C_bool;
  ind : Ind_bool b;
  rel : Rel;
};

Bool = {
  comp : C_bool;
  ind : Ind_bool b;
  rel : Rel;
};

Bool = @Self((A : Type) => (self : T_bool A) => (x : T_bool A) -> self.comp == x.comp -> self == x);
true = %Self((self : Bool) => {
  comp = c_true;
  ind = i_true;
  rel = x => self_comp_eq_x_comp => (
    x_comp_eq_self_comp = symm self_comp_eq_x_comp;
    x_eq_self = x.rel self x_comp_eq_self_comp;
    symm x_eq_self
  );
});
false = %Self((self : Bool) => {
  comp = c_false;
  ind = i_false;
  rel = x => self_comp_eq_x_comp => (
    x_comp_eq_self_comp = symm self_comp_eq_x_comp;
    x_eq_self = x.rel self x_comp_eq_self_comp;
    symm x_eq_self
  );
});
ind_bool = b => (P : Bool -> Type) => (p_t : P true) => (p_f : P false) : P b => (
  (m, b_comp_eq_m_comp, p_m) =
    b.ind
      (x => {m : Bool; x_eq_m_comp : x == m.comp; p_m : P m})
      (true, refl, p_t)
      (false, refl, p_f);
  b_eq_m = b.rel b_comp_eq_m_comp;
  m_eq_b = symm b_eq_m;
  subst m_eq_b (x => P x) p_m
);


T[A := X]
T_bool ((x : Bool) -> self.comp == x.comp -> self == x)

rec%Bool (S : Bool) = (A : Type) -> (S == true -> A) -> (S == false -> A) -> A;
and%true : Bool true = A => t => f => t => t (refl true)
and%false : Bool false = A => t => f => ;

T_bool B T F (S : B) = (A : Type) -> (S == T -> A) -> (S == F -> A) -> A;
X = T_bool
Bool = @Self((A : Type) => (self : T_bool A) => (x : T_bool A) -> self.comp == x.comp -> self == x);
 B : Type -> Type  C : (A : Type) -> A -> Type
----------------------------------------------
    @Self(A : Type, x : B A, C A x) : Type

Bool = {
  comp : C_bool;
  ind : Ind_bool b;
  rel : (x : @Bool) => comp == x.comp -> @self == x;
};
rec%Fix = (self : N : Fix) -> (A : Never) -> A;
fix = (self : N : Fix) => self self;
```

## Compression

```rust
((A : Type\1) => (x : A\1) => x\1) Type\1
(A : Type\1) => ((x : A\2) => x\1)#-1;
((A : Type\1) => (x : A\1) => x\1)#+1

((x : A\0) => x\1)
((x : Type\1) => x\1)-1
(A : Type) => ((B : Type\1) => (x : B\1) => (x\1, A\3)) Type\2;
(A : Type) => (x : Type\1) => (x\1, A\2);

((A : \1) => (x : \1) => \1)#+1#-1

((A : \2) -> (x : ((A : \1) => (x : \1) => \1)#+2) -> ((A : \1) => (x : \1) => \1)#+3)#-1


((A : \1) -> ((x : \1) -> (\2 : (\1)#+2) : \2) : \1)#+1

((A : \1) -> ((x : \1) -> (\2) : \2) : \1)#+1

((A : \1 : (\0 : \0)#+1) -> ((x : \1 : (\1 : (\0 : \0)#+1)#+1) -> (\2 : (\1 : (\0 : \0)#+1)#+2) : \2) : \1)#+1

Levels

((A : Type\1) => (x : A\1) => x\1) Type\1

X

(x := Int; (1 : x))

(one : Int) = 1;
one_eq_1 : one == 1 = refl;
add = (a, b) => a + b;

(x = Int; (1 : x)) === (((x : Type) => (1 : x)) Int);

(x = print 1; (x, x));

(print 1, print 1);

(x : T = e1; e2) === (((x : T) => e1) e2)
(x : T := e1; e2) === (e2[x := e1]);

(x : T = e1; e2) === (((x : T) => e1) e2)
(x : T := e1; e2) === (e2[x := e1]);

x1 = (
  (a : Int, b : Int) = a_b;
  (c_d : (c : Int, d : a == c)) => (
    (c : Int, d : a == c) = c_d;
    a + b + c
  )
) (c = 1; d = d);

x1 = (
  (a, b) = a_b;
  c_d => (
    (c, d) = c_d;
    a + b + c
  )
) (c = 1; d = d);

// church encoding stucks
x1 =
  a_b (a => b =>
    c_d => c_d
      (c => d =>
        a + b + c)
  ) (k => k 1 d);

x1 = (
  (a, b) = a_b;
  c_d => (
    (c, d) = c_d;
    a + b + c
  )
) (c = 1; d = d);

x1 = (
  (a, b) = a_b;
  c_d => (
    (c, d) = c_d;
    a + b + c
  )
) (c = 1; d = d);

x1 = (
  (a, b) = a_b\1;
  c_d => (
    (c, d) = c_d\1;
    a\4 + b\3 + c\2
  )
) (c = 1; d = 2);

x1 = (
  (a, b) = a_b\1;
  c_d => (
    (c, d) = c_d\1;
    a\4 + b\3 + c\2
  )
) (c = 1; d = 2);

x1 = (
  (a, b) = a_b\1;
  c_d => (
    (c, d) = c_d\1;
    a\4 + b\3 + c\2
  )
);

x =>

((a, b) => c_d => (
  (c, d) = c_d\1;
  a\4 + b\3 + c\2
)) a_b\1 (c = 1; d = 2) [id]

((a, b) => c_d => (
  (c, d) = c_d\1;
  a\4 + b\3 + c\2
)) a_b\1 (c = 1; d = 2) [id]

BetaPair : (((x, y) => c) (a, b)) == c[y := b; x := a; ...id]
StuckPair : (((x, y) => c) z)[s] == ((x, y) => c[id; id; s]) z

Next

Linear Booleans

Unit = (A : Type) -> A -> A;
unit : Unit = A => x => x;

Pair (A : Type) (B : A -> Type) = (K : Type) -> ((x : A) -> B x -> K) -> K;
(pair A B x y) : Pair A B = K => k => k x y;

Bool = (A : Type) -> A -> A -> Pair A A;
true : Bool = A => x => y => pair A A x y;
false : Bool = A => x => y => pair A A y x;

Option A = (some : Bool, (T, _) = some Type A Unit; T);
some A (x : A) = (some = true, x);

dup_bool : Bool -> Pair (Pair Bool Bool) (Pair Bool Bool) =
  b => b (Pair Bool Bool) (pair A B true true) (pair A B false false);

Nat = (X : Type) -> ((succ : Bool, zero Type X Unit) -> X) -> X;
zero : Nat = X => k => k (succ = false, unit);
succ : Nat -> Nat = n => X => k => n X k (succ = true, )

Nat = (A : Type) -> A -> ((K : Type) -> A -> A) -> Pair (A -> A) (A -> A);
zero : Nat = A => z => s => Pair (A -> A) (A -> A) z s;
succ : Nat -> Nat = n => A => z => s => s (n)

List A = X -> (((K : Type) -> (A -> X -> K) -> (Unit -> K) -> K) -> X) -> X;
(cons A el tl) : List A = X => k => k (K => cons => nil => cons )
(nil A) : List A = X => k => k (K => cons => nil => nil unit);

dup_list = (A : Type) => (l : List A) => ();

De-bruijin two

one =0> #0;
one =1> #1;

two => one => ((x => y => x\1 + two\3) one\0)
one => ((x => y => x#|1) one#1|0)

one => (y => one\1)

Int -> _A\0 -> _A\1;
Int -> {A} -> A -> A;

((id : (A : Type) -> (x : A) -> A) = A => x => x; id)
        : (A : Type) -> (x : A) -> A)

( := ) : Ref A -> A -> Ref A;

add = (a, b) => a + b;


x = x := 1;

((fix $ 1 : _) => fix fix) ((fix $ 1 : _) => fix fix);

Nat N = (X : Type $ 0) -> (((R : Type $ 0) -> (X -> R) $ N -> R $ 1) $ 1 -> X) -> X;

two = (A : Type) => (z $ 1 : A) => (s $ 2 : A -> A) => s (s x)

double (x : Socket) =
  (l : Int $ 1, r) = x;
  (l : Int $ 1, r) = x;
  x + x;

double (x : Pair (Int $ 1) Int) =
  (l : Int $ 1, r) = x;
  (l : Int $ 1, r) = x;
  x + x;

Modality

zero = x => f => x;
succ = n => x => f => f (n x f);
one = x => f => f x;
two = x => f => f (f x);

zero = k => z => s => k z;
succ = n => k => z => s => s k z n;
one = k => z => s => s k z @@ k => z => s => k z;
two = k => z => s => z => s k z @@ k => z => s => z k s @@ k => z => s => k z;

rec%Nat = (K : Type) -> (A : Type) -> (k : A -> K) -> (z : A) ->
  (s : (k : A -> K) -> (z : A) -> (p : Nat) -> K) -> K;

zero : Nat = K => A => k => z => s => k z;
succ (n : Nat) : Nat = K => A => k => z => s => s k z n;

Id = (A1 : Type) -> (A2 : Type) -> (A1_eq_A2 : A1 == A2) -> (x : A) -> A;

Id = (A $ 2 : Type) -> (x : A) -> A;

id = (A : Type) => (x : A)

// pure system F
Nat X = (K : Type) -> (A : Type) -> (k : A -> K) -> (z : A) ->
  (s : (k : A -> K) -> (z : A) -> (p : X) -> K) -> K;
Nat_m = (X : Type) -> (Nat X -> X) -> X;
Nat_n = Nat Nat_m;

zero : Nat_n = K => A => k => z => s => k z;
in_ : Nat_n -> Nat_m = n => X => w => ;
succ : Nat_n -> Nat_n = n => K => A => k => z => s => s k z (in_ n);


// quantitative
rec%Nat Q = (K : Type) -> (A : Type) -> (k : A -> K) -> (z : A) ->
  (s $ Q : (k : A -> K) -> (z : A) -> (p : Nat Q) -> K) -> K;

id = (A $ 0 : Type) => (x : A $ 1) => x;
y = ((x $ Omega) => x x) ((x $ Omega) => x x)
double = (x $ 2 : Int) => x + x;

Nat Q = (A : Type) -> (z : A) -> (s $ Q : A -> A) -> A;
zero : Nat 0 = A => z => s => z;
succ Q (n $ 1 : Nat Q) : Nat (Q + 1) = A => z => s => s (n A z s);

Z : (self : A -> B) -> A -[Z]> B;

Level : SLevel
Grade : SGrade

(A : Type (L, G))

Type (L : Level, G : Grade) : Type (L + 1, 0);
Erasable (L : Level) = Type (L, 0);
Linear (L : Level) = Type (L, 1);

Nat (G : Grade) : Type (1, G);

(x : Nat : Erasable) =>

----------------
(x : A) -> B

----------------
(x $ 0 : ) -> B

id : A. (x : A) -> A
Pair ()

Nat = (Q : Quantity, Nat Q);
zero : Nat 0 = K => A => k => z => s => k z;
succ Q (n $ 1 : Nat Q) : Nat (Q + 1) = K => A => k => z => s => s k z n;

// TODO: this Q is wrong internally
dup_nat = Q => K => fix%(self => k => (l, r) => (n : Nat Q) =>
  n K (Nat Q, Nat Q) k (succ l, succ r) self);

Either A B =
  | (tag = "left", x : A)
  | (tag = "right", x : B);

Match on Types

// staged compilation

Implicits

// boxing
f = (x : Nat & x >= 1) => x;
{x : Int & x >= 0}

l.1 == r.1 -> l == r?

// overloading
%( == ) :
  (( == ) : {A} -> (x : A) -> (y : A) -> Type) &
  (( == ) : {A : Eq} -> (x : A) -> (y : A) -> x == y);

( == ) : {A} -> (x : A) -> (y : A) -> Type;
%( == ) = {R} =>
  (R, refl : R == R)
  | (Type, eq : R == Type) => ( == )

( == ) = %( == );

Monad = {
  pure : {A} -> (x : A) -> @M A;
  bind : {A} -> (m : @M A, f : (x : A) -> @M B) -> @M B
};

map = (m, f) => bind(m, x => pure(f(x)));
map = {M : Monad} => (m, f) => M.bind(m, x => M.pure)

x = map {Option}
map = {M : _M_T}

C_bool = (A : Type) -> A -> A -> A;
c_true : C_bool = t => f => t;
c_false : C_bool = t => f => f;

Ind_bool : C_bool -> Type =
  b => (P : Bool) -> P c_true -> P c_false -> P b;
ind_true : Ind_bool c_true = t => f => t;
ind_false : Ind_bool c_false = t => f => f;

C_bool = (A $ 0 : (tag = "c", Type)) -> (snd A) -> (snd A) -> (snd A);
c_true : C_bool = A => t => f => t;
c_false : C_bool = A => t => f => f;

I_bool : C_bool -> Type =
  b => (P $ 0 : (tag = "i", Bool -> Type)) -> P c_true -> P c_false -> P b;

Bool = (b : C_bool) & I_bool b;

(T $ 0 : (tag = "i", Bool -> Type) | (tag = "c", Type)) ->
 (P | (tag = "i", P) => P c_true | (tag = "c", A) -> A) ->
 (P | (tag = "i", P) => P c_false | (tag = "c", A) -> t) ->
 (P | (tag = "i", P) => P c_true | (tag = "c", A) -> A) <= (b : C_bool) & I_bool b;

(T $ 0 : (tag = "i", Bool -> Type)) -> (snd T) c_true -> (snd T) c_false -> (snd T) c_true <=
(P $ 0 : (tag = "i", Bool -> Type)) -> (snd P) c_true -> (snd P) c_false -> (snd P) c_true

(T $ 0 : (tag = "c", Type)) -> (snd T) -> (snd T) -> (snd T) <=
(A $ 0 : (tag = "c", Type)) -> (snd A) -> (snd A) -> (snd A);

Either A B = (K : Type) -> (A -> K) -> (B -> K) -> K;
true :
  (T $ 0 : (tag = "i", Bool -> Type) | (tag = "c", Type)) =>
  (t : P | (tag = "i", P) => P c_true | (tag = "c", A) -> A) =>
  (f : P | (tag = "i", P) => P c_false | (tag = "c", A) -> f) =>
  t;


Bool : Type = (b : C_bool) & Ind_bool b;
true : Bool = (b = c_true & ind_true);
false : Bool = (b = c_false & ind_false);

// resolution

Church Induction

b_true : (A $ 0 : Type) -> (B $ 0 : Type) -> A -> B -> A = A => B => t => f => t;
b_false (A $ 0 : Type) -> (B $ 0 : Type) -> A -> B -> B = A => B => t => f => f;

C_bool = (A $ 0 : Type) -> A -> A -> A;
I_bool : C_bool -> Type =
  b => (P $ 0 : Bool -> Type) ->
    P ((A : Type) -> b_true A A) ->
    P ((A : Type) -> b_false A A) ->
    P b;




Bool = (b : C_bool) & I_bool b;
true : Bool = b_true;
false : Bool = b_false;

[x | x => x -A | x => ]
[b_true
  | (A : Type) -> b_true A A
  | (P : Bool -> Type) -> b_true (P ((A : Type) -> b_true A A)) (P ((A : Type) -> b_false A A))
];

b_true : (A $ 0 : Type) -> (B $ 0 : Type) -> A -> B -> A = A => B => t => f => t;
b_false (A $ 0 : Type) -> (B $ 0 : Type) -> A -> B -> B = A => B => t => f => f;

C_bool = (A $ 0 : Type) -> A -> A -> A;
I_bool  =
  (A : Type) => (P : Bool -> Type) =>
    P (b_true A A) ->
    P (b_false A A) ->
    P b;
Bool =
  (A $ 0 : Type) ->
  (P $ 0 : (A -> A -> A) -> Type) ->
  (b : A -> A -> A) &
  (P (b_true A A) -> P (b_false A A) -> P b);

(A : Type) -> b_true &(A; b => P (b A))

(b : (B $ 0 : Type) -> A -> B -> A) & ((B $ 0 : Type) -> P (b A A) -> B -> P (b A A))

S x =
  | (y $ 0 : A) -> S
  | (S x) -A
  | x;

[x | i = ]


[b_true
| (A : Type) -> b_true A A (P : (A -> A -> A) -> Type) -> b_true ]

true : Bool = A => P => (
  x
  x = (A : Type) -> b_true &(A | _ => P (b_false A A));

);
((A $ 0 : Type) -> A -> A -> A) &
((A $ 0 : Type) -> A -> P (b_false A A) -> A)

((B $ 0 : Type) -> A -> B -> A) &
((B $ 0 : Type) -> (P (b_true A A)) -> B -> (P (b_true A A)))

(A $ 0 : Type) -> (B $ 0 : Type) -> A -> B -> A <: (b : C_bool) & I_bool b
  _ <: (A $ 0 : Type) -> A -> A -> A
  _ <: (P $ 0 : Bool -> Type) -> P (b_true :> Bool) -> P (b_false :> Bool) -> P (b_true :> Bool)

Grande e Funções

rec%Term =
  | Var (x : String)
  | Lambda (param : String) (body : Term)
  | Apply (lambda : Term) (arg : Term);

rec%List A =
  | []
  | A :: List

rec%Tree A =
  | Leaf A
  | Node (Tree A, Tree A);

Node (Node (Leaf 1, Leaf 2), Node (Left 3, Leaf 4))
  - Node (Leaf 1, Leaf 2)
    - Leaf 1
    - Leaf 2
  - Node (Left 3, Leaf 4)
    - Leaf 3
    - Leaf 4

rec%fold = (f, acc, l) =>
  l
  | [] => []
  | el :: tl => (
    acc = f(acc, el);
    fold(f, acc, tl)
  );

rec%fold_right = (f, acc, l) =>
  l
  | [] => []
  | el :: tl => (
    acc = fold_right(f, acc, tl);
    f(acc);
  );

sum = (l) => fold((acc, el) => acc + el, 0, l);
rev = (l) => fold((acc, el) => el :: acc, [], l);
map = (f, l) => (
  rev_f_l = fold((acc, el) => f(el) :: acc, [], l);
  rev(rev_f_l)
);

rec%map = (f, l) =>
  l
  | [] => []
  | el :: tl => f(el) :: map(f, tl);

rec%map = (f, l) =>
  l
  | [] => []
  | el :: tl => map_cons(f, el, tl)
and%map_cons = (f, el, tl) => f(el) :: map(f, tl);

map_cons = map => (f, el, tl) => f(el) :: map(f, tl);
map_base = map => (f, l) => l | [] => [] | el :: tl => map_cons(map)(f, el, tl)

map_base = map => (f, l) => l | [] => [] | el :: tl => map(f, el, tl)

Y = f => (x => f(x(x)))(x => f(x(x)));
loop = (x => x(x))(x => x(x));
loop = (x => x(x))(x => x(x));
loop = (x => x(x))(x => x(x));

map = (x => map_base(x(x)))(x => map_base(x(x)));
map = map_base((x => map_base(x(x)))(x => map_base(x(x))));
map = map_base(map_base((x => map_base(x(x)))(x => map_base(x(x)))));

rec%map = (f, l) => map_base(map, f, l);

rec%Many A = (G : Grade) -> (A G, Many A);

rec%Fix = Fix $ Many -> Unit;

Int : G. Type (1, G);

{A} -> {M : Monad} -> M A -> M B;
f = G. (x : Int) => (
  g : Unit -> Int = () => x;
  (g(), g())
);

Type L G : Type (L + 1, 0)

f = (x : $Int) => (x, x : Int $ 0);

f = (A : Type) => A;
f = x => (
  (x1, x) = x;
  x1(x)
);

(x : (A : Type) -> A)

Recursion

rec%Fix = (A : Type) -> (B : Type) -> (A -> B) -> A -> B;

%fix : (Type -> Type) -> Type;
fix = (A : Type) => (B : Type) => (f : %fix(K => ))
fix = (A : Type) => (f : %fix(K => K -> A)) : A => f(f)

%fix(Self => Self -> T) ===

%Mu : (W : Type -> Type) -> Type;
%mu : (W : Type -> Type) -> Mu W == W (Mu W);

%Mu(Self => Self -> T) == (%Mu(Self => Self -> T)) -> T



-------------------------------
Y : (A : Type) -> (A -> A) -> A

Equal A (x : A) (y : A) = (P : _) -> P x -> P y;

Bool = (H : )

Induction

T_bool = Type -> Type -> Type;
t_true : T_bool = t => f => t;
t_false : T_bool = t => f => f;

Bool (H : T_bool) = (A : Type) -> (H == t_true -> A) -> (H == t_false -> A) -> A
true : Bool t_true = A => t => f => t refl;
false : Bool t_false = A => t => f => f refl;

ind_bool
  : (H : T_bool) -> (b : T_bool H) -> (P : T_bool -> Type) -> P t_true -> P t_false -> P H =
  b => P => p_t => p_f =>
  b p_t p_f

TRec F = (X : Type) ->
Rec F = (X : Type) -> (F X -> X) -> X;
M = Rec (X => (A : Type) -> A -> (X -> A) -> A);
N = Rec M;

T_nat = Type -> (Type -> Type) -> Type
t_zero : T_nat = z => s => z;
t_succ : T_nat -> T_nat = pred => z => s => s (pred z s);
t_add : T_nat -> T_nat -> T_nat = n => m => z => s => n (m z s) s;

t_add (t_succ n_t_pred) m_t == (z => s => s (n_t_pred (m_t z s) s))
t_succ (t_add n_t_pred m_t) == (z => s => s (n_t_pred (m_t z s) s))


rec%Nat (H : T_nat) =
  (A : Type) ->
  (H == t_zero -> A) ->
  ((t_pred : T_nat) -> H == t_succ t_pred -> Nat t_pred -> A) ->
  A;
zero : Nat t_zero = A => z => s => z refl;
succ : (t_pred : T_nat) -> (pred : Nat t_pred) -> Nat (t_succ t_pred) =
  t_pred => pred => A => z => s => s t_pred refl pred);
rec%add
  : (n_t : T_nat) -> Nat n_t -> (m_t : T_nat) -> Nat m_t -> Nat (t_add n_t m_t)
  = n_t => n => m_t => m => A => z => s =>
    n (Nat (t_add n_t m_t))
      (n_t_eq_t_zero => m)
      (n_t_pred => n_t_eq_t_succ_n_t_pred => pred =>
        x : Nat (t_add n_t_pred m_t) = add n_t_pred pred m_t m;
        x : Nat (t_succ (t_add n_t_pred m_t)) = succ x;
        t_add n (t_succ m));

Never = (A : Type) -> A;
Unit = (A : Type) -> A -> A;
unit : Unit = A => x => x;
z_neq_s_z (eq : t_zero == t_succ t_zero) =>
  eq (n => n Unit (_ => Never)) unit;

rec%T_nat = Type -> (T_nat -> Type) -> Type;
t_zero : T_nat = z => s => z;
t_succ : T_nat -> T_nat = pred => z => s => s pred;
rec%t_add : T_nat -> T_nat -> T_nat = n => m => z => s =>
  n m (n => t_add n (t_succ m));

rec%Nat (H : T_nat) =
  (A : Type) ->
  (H == t_zero -> A) ->
  ((t_pred : T_nat) -> H == t_succ t_pred -> Nat t_pred -> A) ->
  A;
zero : Nat t_zero = A => z => s => z refl;
succ : (t_pred : T_nat) -> (pred : Nat t_pred) -> Nat (t_succ t_pred) =
  t_pred => pred => A => z => s => s t_pred refl pred;

Nat

let f (type a) (ty : a ty) (x : a) =
  match ty with Int -> string_of_int (x : int) | String -> (x : string)

type 'x nat_case' = { case : 'r. 'r -> ('x -> 'r) -> 'r }
type nat_iter = { iter : 'x. ('x nat_case' -> 'x) -> 'x }
type nat_case = nat_iter nat_case'

let zero_iter : nat_iter = { iter = (fun f -> f { case = (fun z _s -> z) }) }

let succ_iter : nat_iter -> nat_iter =
 fun n ->
  {
    iter =
      (fun (type x) (f : x nat_case' -> x) : x ->
        f
          { case =
            (fun (type r) (_z : r) (s : x -> r) : r -> s (n.iter f)) });
  }

let in_ : nat_case -> nat_iter = fun n -> n.case zero_iter succ_iter
let zero_case : nat_case = { case = (fun z _s -> z) }

let succ_case : nat_case -> nat_case =
 fun n -> { case = (fun _z s -> s (in_ n)) }

let out : nat_iter -> nat_case =
 fun n -> n.iter (fun f : nat_case -> f.case zero_case succ_case)

let case (n : nat_case) z s = n.case z (fun pred -> s (out pred))
let iter (n : nat_case) z s = (in_ n).iter (fun n -> n.case z s)
let to_int (n : nat_case) = (in_ n).iter (fun n -> n.case 0 (fun n -> n + 1))

let () =
  Format.printf "%d\n%!" (to_int (succ_case (succ_case (succ_case zero_case))))

Subtyping

A | B

A :> A | B
B :> A | B

A <: A | B
B <: A | B

A | B <: C
  A <: C && B <: C

C <: A | B
  C <: A || C <: B

(tag : true, Int) | (tag : false, String) <: (tag : Bool, tag Type Int String)

1 * 0 = 2 * 0
0 = 0
(1 * 0) / 0 = (2 * 0) / 0
1 = 2


(n * x) / x && x <> 0 == n

(1 * 0) / 0 = (2 * 0) / 0

(L : Level) -> (A : Type L, x : A)

ADTs

Nat : {
  @Nat : Type;
  zero : Nat;
} = {
  @Nat = Int;
  zero = 0;
};

(==) :
  ((==) : {A} -> (x : A) -> (y : A) -> Type) &
  {A : Eq} -> (x : A) -> (y : A) -> Option (x == y);


zero : Nat = Nat.zero;

f = (x : Int & x >= 0) => (x : Int);

S = {x : T | P x}

Nat = {x : Z | x >= 0};

Either A B =
  | { tag = true; payload : A; }
  | { tag = false; payload : B; };

M : {
  T : Type;
  x : T;
} = {
  T = Int;
  x = 1;
};

Induction of Union

Id = (A : Type) -> A -> A;
id : Id = (A : Type) => (x : A) => x;

Bool = (A : Type) -> A -> A -> A;
true : Bool = (A : Type) => (x : A) => (y : A) => x;
false : Bool = (A : Type) => (x : A) => (y : A) => y;

Interval : UI;
Level : UL;
Grade : UG;

data%Bool = true | false;

ind%Eq (A : Type) (x : A) (y : A) : Type =
  | refl : x == y;
Eq_refl : (A : Type) -> (x : A) -> Eq A x x;
Eq_ind : (A : Type) -> (x : A)

: (A : Type) -> (x : A) -> (P : (y : A) -> id x y -> Type) ->
       P x (refl x) ->
       ((y : A) -> P y (nope x y)) ->
       (y : A) -> (eq : id x y) -> P y eq

ind%Nat =
  | O
  | S (pred : Nat);

ind%Bool = | true | false;
Bool_ind :
  (P : Bool -> Type) ->
  (p_true : P true) ->
  (p_false : P false) ->
  (b : Bool) -> P b;
Bool_ind : (b : Bool, P : Bool -> Type, _ : P true, _ : P false) -> P b;

id<A>(x : A) = x;
Either(A, B) =
  | (tag = true, x : A)
f = (x : Int | String) => (y : Int, x_eq_int : x == y) => (

)

f x == f y -> x == y
X B k == Y B k -> X A (x => x) = Y B (x => x)

X : (B : Type) -> (A -> B) -> Type;
k : A -> B


x => k (f x)
x => (f x)

Induction

// compute
fold : Bool -> (A : Type) -> A -> A -> A;
// induction
case :
  (b : Bool) -> (P : Bool -> Type) ->
  P true -> P false -> P b;



Eq A x y = (P : A -> Type) -> P x -> P y;

rec%Bool =
  (A : Type) -> (P : Bool -> Type) -> P true -> P false -> P

(Eliminating a boolean B) shows that the boolean B is true or false.

Bool : Type = self%(b => (P : Bool -> Type) -> P true -> P false -> P b);
true : Bool = _;
false : Bool = _;
ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b = _;

Unit = (A : Type) -> A -> A;
unit : Unit = A => x => x;

Bool A T F = (H : A, ind : (P : A -> Type) -> P T -> P F -> P H);

Bool_0 = Bool Unit unit unit;
true_0 : Bool_0 = (H = _, ind = P => p_t => p_f => p_t);
false_0 : Bool_0 = (H = _, ind = P => p_t => p_f => p_f);

Bool_1 = Bool Bool_0 true_0 false_0;
true_1 : Bool_1 = (H = _, ind = P => p_t => p_f => p_t);
false_1 : Bool_1 = (H = _, ind = P => p_t => p_f => p_f);

Bool_2 = Bool Bool_1 true_1 false_1;
true_2 : Bool_2 = (H = _, ind = P => p_t => p_f => p_t);
false_2 : Bool_2 = (H = _, ind = P => p_t => p_f => p_f);

C_nat = (A : Type) -> A -> (A -> A) -> A;
c_zero : C_nat = A => z => s => z;
c_succ : C_nat -> C_nat => n => A => z => s => s z;

C_bool = (A : Type) -> A -> A -> A;

Bool (n : C_nat) =
  n Type C_bool (A => (H : A, (P : A -> Type) -> P T -> P F -> P H));

case_2
  : Bool_2 -> (A : Type) -> A -> A -> A
  = (b : Bool_2) => (A : Type) => fst b (_ => A);
ind_2
  : (b : Bool_2) -> (P : _ -> _) -> P true_1 -> P false_1 -> P (fst b)
  = (b : Bool_2) => snd b;

Qual a melhor linguagem de programação?

  • JavaScript
  • PHP
  • Python

JavaScript é a melhor linguagem de programação?

  • Sim
  • Não

    Então Python é a melhor linguagem de programação?

Qual a mãe de todas as linguagens de programação?

Qual a melhor linguagem de programação? Por que JavaScript não é a melhor linguagem de programação?

Qual a melhor forma de conseguir o primeiro emprego?

Qual a forma você recomenda para conseguir o primeiro emprego?

Estou programando a 6 meses, qual a forma você recomenda para eu conseguir o primeiro emprego?

Como eu aprendo JavaScript?

  • A: Ler livros sobre JavaScript
  • B: Entrar em comunidades de JavaScript
  • C: Ler a wikipedia sobre JavaScript
  • D: Ver video no youtube sobre JavaScript
  • E: Fazer um curso de 3k de JavaScript

Por que eu não aprendi JS com o livro X?

Por que os metodos acima não funcionaram?

  • A: Procuro no Google sobre JavaScript

Por que eu não consigo encontrar uma hipotese?

  • Eu não tenho contexto o suficiente

Por que eu não consigo solucionar esse problema em X?

  • A: Eu não sei X o suficiente

Por que eu não tenho uma hipotese?

Data Macro

data%Bool =
  | true
  | false;

pair A B (x : A) (y : B x) =
  (K : Type) => k => k x y;

Sigma A B =
  %self(Sigma, s).
    (P : Sigma -> Type) ->
    ((x : A) -> (y : B x) -> P (%fix(Sigma, s). P => k => k x y)) ->
    P s
Sigma A B =
  %self(Sigma, s).
    (P : Sigma -> Type) ->
    ((x : A) -> (y : B x) -> P (%fix(Sigma, s). P => (k : _ -> _ -> P s) => k x y)) ->
    P s;

%fix(Bool, b) =>
Bool =
  %self(Bool, b).
    (P : Bool -> Type) ->
    P (%fix(Bool, b). P => ())

sigT_rect
	 : forall (A : Type) (P : A -> Type) (P0 : {x : A & P x} -> Type),
       (forall (x : A) (p : P x), P0 (existT P x p)) ->
       forall s : {x : A & P x}, P0 s


Unit = %fix(Unit). %self(u).
  (P : Unit -> Type) ->
    P (%fix(u). (P : Unit -> Type) => (x : P u) => x) ->
    P u;

%unroll(%fix(u). (P : Unit -> Type) => (x : P u) => x)
%self(u). (P : Unit -> Type) -> P (%fix(u). (P : Unit -> Type) => (x : P u) => x) -> P u
%self(u). (P : Unit -> Type) -> P (%unroll(%fix(u). (P : Unit -> Type) => (x : P u) => x)) -> P u

(x ) => x

@(x) ->
@(x) =>




Unit = %fix(Unit : Type). %self(u).
  (P : Unit -> Type) -> P u -> P u;

ctx = [];
fix0 = %fix(Unit). %self(u). (P : Unit -> Type) ->
  P (%fix(u). (P : Unit -> Type) => (x : P u) => x) -> P u;

ctx = [];
fix1 = %self(u). (P : fix0 -> Type) ->
  P (%fix(u). (P : fix0 -> Type) => (x : P u) => x) -> P u;


ctx = [u : fix1];
fix2 = (P : fix0 -> Type) ->
  P (%fix(u). (P : fix0 -> Type) => (x : P u) => x) -> P u;

ctx = [P : fix0 -> Type; u : fix1];
fix3 = P (%fix(u). (P : fix0 -> Type) => (x : P u) => x) -> P u;
  ctx = [P : fix0 -> Type; u : fix1];
  u0 : ? = %fix(u). (P : fix0 -> Type) => (x : P u) => x;
  u1 : %self(u). ? = (P : fix0 -> Type) => (x : P u0) => x;
  u2 : %self(u). (P : fix0 -> Type) -> ? = (x : P u0) => x;
  u3 : %self(u). (P : fix0 -> Type) -> P u0 -> P u0 = _;
  u0 : %self(u). (P : fix0 -> Type) -> P u0 -> P u0 = _;

  expected : fix0;
  received : %self(u). (P : fix0 -> Type) -> P u0 -> P u0;

  expected : %fix(Unit). %self(u). (P : Unit -> Type) ->
    P (%fix(u). (P : Unit -> Type) => (x : P u) => x) -> P u;
  received : %self(u). (P : fix0 -> Type) -> P u0 -> P u0;

  expected : %self(u). (P : fix0 -> Type) -> P u0 -> P u;
  received : %self(u). (P : fix0 -> Type) -> P u0 -> P u0;

Unit = %fix(Unit). %self(u).
  (P :
    (
      %self(u). (P : -> Type) ->
        P (%fix(u). (P : Unit -> Type) => (x : P u) => x) -> P u
    ) ->
    Type
  ) ->
  P (%fix(u). (P : Unit -> Type) => (x : P u) => x) ->
  P u;

%self(u). P

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ |- M[x := %fix(x). M] : T
-------------------------------
      %fix(x). M : T


%fix(u). (x : P u) => x

u : _A
(x : P u) -> _A
_A := %self(u). (x : P u) -> _A

%fix(u). (x : P u) => u : %self(u). (x : P u)

%fix(u : %fix(T). %self(u). (x : P u) -> T).
  (x : P u) => u

%self(u). (x : P u) -> %fix(T). %self(u). (x : P u) -> T
%self(u). (x : P u) -> %fix(T). %self(u). (x : P u) -> T

%fix(T). %self(u). (x : P u) -> T
%self(u). %fix(T). (x : P u) -> T

unit
  : %fix(Unit : Type). %self(u). (P : Unit -> Type) -> P u -> P u
  = %fix(u). (P : Unit -> Type) => (x : P u) => x

Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) ->
  P unit -> P u;

ctx = [];
s0 = %fix(Unit : Type). %self(u). (P : Unit -> Type) -> P unit -> P u;

s1 = %self(u). (P : s0 -> Type) ->
  P unit -> P u;

ctx = [u : s0]
s2 = (P : s0 -> Type) -> P unit -> P u;

ctx = [u : s0; P : s0 -> Type]
s3 = P unit -> P u;


expected : s0
received : %fix(Unit : Type). %self(u). (P : Unit -> Type) -> P u -> P u

expected : %fix(UnitA : Type). %self(u). (P : UnitA -> Type) -> P unit -> P u
received : %fix(UnitB : Type). %self(u). (P : UnitB -> Type) -> P u -> P u

s4 = P (%fix(u : s0). (P : s0 -> Type) => (x : P u) => x) -> P u;


expected : %fix(A). () -> A
received : %fix(B). () -> B

expected : %fix(C). () -> () -> A
received : %fix(C). () -> B

expected : () -> %fix(A). () -> A
received : () -> %fix(B). () -> B





Γ, x : Id |- T : Type
---------------------
%self(0, x. T) : Type

Γ, x : %self(i, x. T) |- T : Type
---------------------------------
%self(i + 1, x. T) : Type

Γ |- M[x := id] : T
---------------------
%fix(0, x : T. M) : T

Γ |- M[x := %fix(0, x : T. M)] : T
----------------------------------
%fix(i + 1, x : T. M) : T

%fix(i, Unit.
  %self(i, u. (P : Unit -> Type) ->
    P ((P : Unit -> Type) => (x : P u) => x) -> P u))

Unit = %fix(Unit). %self(u).
  (P : Unit -> Type) -> P ((P : Unit -> Type) => (x : P u) => x) -> P u;
unit : Unit = %fix(u). (P : Unit -> Type) => (x : P u) => x;

%fix(Unit). %self(u).
  (P : Unit -> Type) -> P ((P : Unit -> Type) => (x : P u) => x) -> P u


%fix(T). %self(u).


Γ, x : A |- B : Type  A === %self(x : A). B
-------------------------------------------
          %self(x : A). B : Type

Γ |- M[x := %fix(x : A). M] : B
--------------------------------
%fix(x : A). M : %self(u : A). B

%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x

%fix(Unit : Type). %self(u : Unit).
  (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) ->
  P u;



%fix(Unit : Type). %self(u : Unit).
  (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) ->
  P u;

%fix(u) : %fix(Unit : Type). (P : Unit -> Type) -> P u -> P u.
  (P : Unit -> Type) => (x : P u) => x

%self(u : Unit). (P : Unit -> Type) -> P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u
%self(u : Unit). (P : Unit -> Type) -> P u -> P u;

%fix(T : Type). %self(u : T). (P : T -> Type) -> P u -> P u



%fix(Unit : Type). %self(u : Unit).
  (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) ->
  P u;


%fix(False) : Type. %self(f). (P : !False -> Type) -> P f

%fix(False) : Type. %self(f : !False). (P : !False -> Type) -> P f

%fix(False) : Type.
  %self(f : (%self(f : False). (P : False -> Type) -> P f)). (P : !False -> Type) -> P f

(%self(f : False). (P : False -> Type) -> P f) ==
%self(f : False). (P : False -> Type) -> P f

!False <: False
f : (P : !False -> Type) -> P f

%fix(False) : Type. %self(f).
  (P : (%self(f). (P : False -> Type) -> P f) -> Type) -> P f
%self(f). (P : !False -> Type) -> P f


%fix(Unit) : Type. %self(u).
  (P : (%self(u). (P : Unit -> Type) -> P u -> P u) -> Type) ->
  P (
    %fix(u) : (P : Unit -> Type) -> P u -> P u.
      (P : Unit -> Type) => (x : P u) => x
  ) -> P u


%fix(u : )

() = check (1 + 1) 2;

%fix(Unit : Type). %self(u : Unit).
  (P : Unit -> Type) ->
  P (
    %fix(u) : (P : Unit -> Type) -> P u -> P u.
      (P : Unit -> Type) => (x : P u) => x
  ) -> P u

Either A B =
  | (left = true, content : A)
  | (left = false, content : B);

Either A B = (left : Bool, content : Bool Type A B);

%fix(Unit : Type). %self(u : Unit).
  (P : !Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u

%fix(Unit : Type). %self(u : Unit).
  (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u


Γ, x : A |- B : Type  A === %self(x : A). B
-------------------------------------------
%self(x : A). B : Type

Γ |- M[x := %fix(x : A). M] : B  A === %self(x : A). B
------------------------------------------------------
%fix(x : A). M : A


Γ |- M[x := [%fix(x : A). M[!x := x]]] : B  A === %self(x : A). B
------------------------------------------------------
%fix(x : A). M : A

Γ |- M : %self(u : A). B
-------------------------------
%unroll(M) : B[u := %unroll(M)]

Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u;


Unit = %fix(Unit : Type).
  %self(u : !Unit). (P : !Unit -> Type) -> P u -> P u;

!Unit === %self(u : !Unit). (P : !Unit -> Type) -> P u -> P u
![%self(u : !Unit). (P : !Unit -> Type) -> P u -> P u] === %self(u : !Unit). (P : !Unit -> Type) -> P u -> P u
%self(u : !Unit). (P : !Unit -> Type) -> P u -> P u === %self(u : !Unit). (P : !Unit -> Type) -> P u -> P u

Unit = %fix(Unit : Type).
  %self(u : %self(u : !Unit). (P : !Unit -> Type) -> P u -> P u).
    (P : (%self(u : !Unit). (P : !Unit -> Type) -> P u -> P u) -> Type) ->
    P u -> P u;

Unit = %fix(Unit : Type).
  %self(u : !Unit). (P : !Unit -> Type) -> P u -> P u;

Unit = %fix(Unit : Type).
  %self(u : !Unit). (P : !Unit -> Type) -> P u -> P u;
Unit = %fix(Unit : Type).
  %self(u : !). (P : !Unit -> Type) ->
  P u -> P u;

unit
  : %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) -> P u -> P u
  = %fix(u). (P : Unit -> Type) => (x : P u) => x;

Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) -> P unit -> P u;

%self(u : (%fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) -> P unit -> P u)). (P : (%fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) -> P unit -> P u) -> Type) -> P unit -> P u
%fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) -> P u -> P u

unit = %fix(u : Unit). (P : Unit -> Type) => (x : P u) => x;

ind_unit = (P : Unit -> Type) => (p : (u : Unit) =>
  u
   (P : Unit -> Type) -> P unit ->

%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x

%self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u
===
%self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u
%self(u : Unit).
  (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u



%self(u : Unit). (P : Unit -> Type) -> P u -> P u

unit
  : %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) -> P u -> P u
  = %fix(u). (P : Unit -> Type) => (x : P u) => x;

Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) -> P unit -> P u;

Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u;

%fix(true : Bool).
        (P : Bool -> Type) => (then : P true) =>
        (else : P (%fix(false : Bool).
          (P : Bool -> Type) =>
          (then : P (%fix(true). (P : Bool -> Type) => (then : P true) => (else : P false) => then)) =>
          (else : P false) => else
        )


Bool = %fix(Bool : Type). (
  %self(b : Bool). (P : Bool -> Type) ->
    P (%fix(true : Bool).
        (P : Bool -> Type) => (then : P true) =>
        (else : P (%fix(false : Bool). (P : Bool -> Type) => (then : P true) => (else : P false) => else)) =>
        then) ->
    P (%fix(false).
        (P : Bool -> Type) =>
        (then : P (%fix(true). (P : Bool -> Type) => (then : P true) => (else : P false) => then)) =>
        (else : P false) =>
        else)) ->
    P b
)

Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u;

Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u;


False = %fix(False : Type). %self(f : False). (P : False -> Type) -> P f;
False === %self(f : False). (P : False -> Type) -> P f

Sigma === %fix(Sigma) => A => B =>
  %self(s : Sigma A B). (P : Sigma A B -> Type) ->
    ((x : A) -> (y : B x) ->
      P (%fix(s : Sigma A B). (P : Sigma A B -> Type) =>
          (k : (x : A) -> (y : B x) -> P s) => k x y) ->
    P s;

%self(s : Sigma A B). (P : Sigma A B -> Type) ->
    ((x : A) -> (y : B x) ->
      P (%fix(s : Sigma A B). (P : Sigma A B -> Type) =>
          (k : (x : A) -> (y : B x) -> P s) => k x y) ->
    P s === %self(s : Sigma A B). (P : Sigma A B -> Type) ->
    ((x : A) -> (y : B x) ->
      P (%fix(s : Sigma A B). (P : Sigma A B -> Type) =>
          (k : (x : A) -> (y : B x) -> P s) => k x y) ->
    P s

False = %fix(False : Type). %self(f). (P : False -> Type) -> P f;
False === %self(f). (P : False -> Type) -> P f




expected : Unit
received : %self(u : Unit). (P : Unit -> Type) -> P u -> P u
alias : u === %fix(u : Unit). (P : Unit -> Type) => (x : P u) => x

expected : %self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u
received : %self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u


%fix(Y). Y -> ();

Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u;

%fix(False : Type). %self(f : False). (P : False -> Type) -> P f;
False === %self(f : False). (P : False -> Type) -> P f

%self(f : False). (P : False -> Type) -> P f

False ===


%fix(False : Type). %self(f : False 1). (P : False 0 -> Type) -> P f;

Γ, x : A |- B : Type  A === %self(x : A). B
-------------------------------------------
%self(x : A). B : Type

Γ, x : X, r : %self(r). Eq X M x |- M : X
------------------------------------------
%fix(x : X, r). M : X

%fix(Unit : Type, eq). %self(u). (P : Unit -> Type) ->
  P (
    %fix(u : Unit, r).
      eq (T => T)
      (P : Unit -> Type) => (x : P u) => x))
  P (eq (T => T) u);

Eq A (x y : A) = (P : A -> Type) -> P x -> P y;
%fix(False : Type, eq).
  %self(f). (P : False -> Type) -> P (eq (T => T) f);


Unit : Type
unit : Unit;

Unit = %self(u). (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;

False : Type
False = %self(f). (P : False -> Type) -> P f;

Unit = %fix(False).
  %self(u). (P : Unit unit -> Type) -> P unit -> P u;

Why?

The natural internalization of dependent elimination requires a term that depends on itself on the type level.

A term that depends on itself, is a term introduced by a fixpoint.

Such a fixpoint requires a type to represent the self dependency, we call that a self type.

// formation
Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type
// introduction
Γ |- M[x := M] : T
---------------------------
%fix(x). M : %self(x). T

A self type variable can only appear in a type constructor position, as such the expected type of such constructor must be the self type itself.

Due to that, the self type usage requires a type fixpoint. But such a type needs to be checkable against the self variable itself.

// somehow (f : False), to allow (P f)
%fix(False). %self(f). (P : False -> Type) -> P f

Somehow control the internal expansion

False : Type
False = %self(f : False). (P : False -> Type) -> P f


Unit = %fix(Unit : Type). %self(u : Unit). (P : Unit -> Type) ->
  P (%fix(u : Unit). (P : Unit -> Type) => (x : P u) => x) -> P u;
unit : Unit = %fix(u : Unit). (P : Unit -> Type) => (x : P u) => x;

ind : (P : Unit -> Type) -> P unit -> (u : Unit) -> P u =
  (P : Unit -> Type) => (x : P unit) => (u : Unit) => u P x;
f = (u : Unit) : Eq Unit u unit =>
  u (u => Eq Unit u unit) eq_refl;

False = %fix(False : %self(False). (%self(f). False f) -> Type).
  (f : %self(f). False f) => (P : False f -> Type) -> P f;
False = %self(f). False f;


Unit =
  %fix(Unit : %self(Unit).
    (u : %self(u). (unit : %self(unit). Unit u unit) -> Unit u unit) ->
    (unit : %self(unit). Unit u unit) -> Type
  ). u => unit => (P : Unit u unit -> Type) -> P unit -> P (u unit);
unit = %fix(u). (unit : %self(unit). Unit u unit) ->

Unit =
  %fix(Unit : %self(Unit).
    (unit : %self(unit). (u : %self(u). Unit unit u) -> Unit unit u) ->
    (u : %self(u). Unit unit u) -> Type
  ). unit => u => (P : Unit unit u -> Type) -> P (unit u) -> P u;

unit : %self(unit). Unit (_ => unit) unit =
  (P : Unit (_ => unit) unit -> Type) => (x : P unit) => x;


Unit = %self(u).
  Unit u (%fix(unit : ) : (P : Unit u unit -> Type) => (x : P unit) => x);

Unit =
  %fix(Unit : %self(Unit).
    (unit : %self(unit). (u : %self(u). Unit unit u) -> Unit unit u) ->
    (u : %self(u). Unit unit u) -> Type
  ). unit => u => (P : Unit unit u -> Type) -> P (unit u) -> P u;

x = (f : False) =>

Unit = %fix(Unit : %self(Unit). (%self(unit). Unit unit) -> Type).
  (unit : %self(unit). Unit unit) =>
    (u : Unit unit) => (P : Unit unit -> Type) -> P unit -> P u;
unit = %fix(unit : %self(unit). Unit unit).
  (u : Unit unit) => (P : Unit unit -> Type) => (x : P unit) => x;

%fix(False).
  (eq : Eq Type (False eq) (%self(f : False eq, eq). (P : False eq -> Type) -> P f)) =>
    %self(f : False eq, eq). (P : False eq -> Type) -> P f

// introduction
Γ, f : {f | x : A} -> B, x : A |- B : Type
------------------------------------------
      {f | (x : A) -> B} : Type

{u | (P : _) -> P {u | P => x => x} -> P u}

External Constructors

Unit =
  %fix(Unit : %self(Unit). (%self(u). Unit u) -> Type).
    u => (P : Unit unit u -> Type) -> P u -> P u;
unit = %fix(u : Unit u). (P : Unit u -> Type) => (x : P u) => x;

fix%Unit (u : %self(u). Unit u) : Type = (P : Unit u -> Type) -> P u -> P u;
fix%unit : Unit unit = (P : Unit u -> Type) => (x : P unit) => x


Unit : (u : %self(u). Unit u) -> Type;
unit : %self(u). Unit u;

Unit = u => (P : (%self(u). Unit u) -> Type) -> P unit -> P u;
unit = %fix(unit) : Unit unit. (P : (%self(u). Unit u)) => (x : P unit) => x;

fix%Unit (u : %self(u). Unit u) : Type = (P : Unit u -> Type) -> P u -> P u;

%self(unit). (u : %self(u). Unit unit u) ->
  (P : Unit unit u -> Type) -> P (unit u) -> P (u => (P : Unit unit u -> Type) => (x : P (unit u)) => x))
unit = %fix(u). (unit : %self(unit). Unit u unit) ->


Unit = %fix(Unit : %self(Unit). (%self(u). Unit u) -> Type).
  (u : %self(u). Unit u) => (P : (%self(u). Unit u) -> Type) -> P u;

False = %fix(False : %self(False). (%self(f). False f) -> Type).
  (f : %self(f). False f) => (P : (%self(f). False f) -> Type) -> P f;
False = %self(f). False f;

Unit = %fix(Unit) : (unit : %self(u). Unit u u) -> (%self(u). Unit unit u) -> Type.
  unit => u => (P : (%self(u). Unit unit u) -> Type) -> P unit -> P u;
unit : %self(u). Unit u u = %fix(u) : Unit u u.
  (P : (%self(u). Unit u u) -> Type) => (x : P u) => x;
Unit = %self(u). Unit unit u;


unit : Unit = unit;

Bool = %fix(Bool) :
  (true : %self(true).
    (false : %self(false). Bool (true false) false false) -> Bool (true false) false (true false)) ->
  (false : %self(false). Bool (true false) false false) ->
  (%self(b). Bool (true false) false b) -> Type.
  true => false => b =>
    (P : (%self(b). Bool (true false) false b) -> Type) -> P (true false) -> P false -> P b;
true : %self(true). (false : %self(false). Bool (true false) false false) -> Bool (true false) false (true false)
  = %fix(true). false => (then : P (true false)) => (else : P false) => then;
false : %self(false). Bool (true false) false false
  = %fix(false). (then : P (true false)) => (else : P false) => else;
Bool = %self(b). Bool (true false) false b;
true : Bool = true false;
false : Bool = false;





%self(False). (%self(f). False f) -> Type;

False : %self(f). False f -> Type


Unit : %self(Unit). (u : %self(u). Unit u) -> Type;
unit : %self(u). Unit u;

Unit = u => (P : %self(u). Unit u) -> P unit -> P u;
unit = P => x => x;

// tie the knot
Unit = %self(u). Unit u;


fix%False (f : %self(f). False f) : Type
  = (P : (%self(f). False f) -> Type) -> P f;
False = %self(f). False f;


unit : %self(unit). Unit unit (%unroll unit)

%unroll unit : Unit unit (%unroll unit)

unroll Unit = (unit : %self(u). Unit u u) : %self(u). Unit unit u =>

  %fix(u) : Unit unit u. unit : Unit unit unit;


fix%Unit (unit : %self(unit). Unit unit unit) (u : %self(u). Unit unit u) : Type
  = (P : (%self(unit). Unit unit u) -> Type)-> P unit -> P u;
fix%unit : Unit unit (%unroll unit) =
  (P : (%self(u). Unit unit u) -> Type) => (x : P (%unroll unit)) => x;
Unit = %self(u). Unit unit u;

%self(unit). Unit unit (%unroll unit)
%self(unit). Unit unit (%unroll unit)

%self(unit). (P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P (%unroll unit)

fix%Unit (unit : %self(unit). Unit unit unit)
  (u : %self(u). Unit unit u) : Type
  = (P : (Unit unit u) -> Type) -> P (%unroll unit) -> P (%unroll u);

%self(u). Unit unit unit

%self(unit). Unit unit unit

fix%unit : %self(unit). Unit unit (%unroll unit) = %fix(u) : Unit unit u.
  (P : (Unit unit u) -> Type) => (x : P (%unroll unit)) => x;


(P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P (%unroll unit)
(P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u



Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, x : %self(x). T |- M : T
----------------------------
%fix(x) : T. M : %self(x). T

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]

False : _A
  f : %self(f). _B
    _A := _C -> Type;
    _C := (%self(f). _B);
    _B := False f;
  f : %self(f). False f
False : (f : %self(f). False f) -> Type



False : lazy ((f : %self(f). False f) -> Type)
False : (f : lazy (%self(f). False f)) -> lazy Type
  f : lazy (%self(f). False f)
    // False f
    False : (f : lazy (%self(f). False f)) -> lazy Type



%fix(False) : (f : %self(f). False f) -> Type. Type;

%fix(Unit): (unit : %self(unit). Unit unit (%unroll unit)) (u : %self(u). Unit unit (%unroll u))
   = Type;
Unit : _A;
_A := (unit : _B) -> (u : _C) -> Type
  unit : _B
  _B := %self(unit). _D
  (%unroll unit : _C)

(unit : _A) -> (u : _B) -> Type

_A === %self(unit). Unit unit (%unroll unit)
(%unroll unit : _B)

_B === %self(u). Unit unit (%unroll u)
(%unroll u : _B)

_A === %self(unit). Unit unit (%unroll unit)



fix%Unit (unit : %self(a). Unit a a) (u : %self(u). Unit unit u) : Type
  = (P : (%self(u). Unit unit u) -> Type) -> P unit -> P u;
fix%unit : Unit unit (%unroll unit) = P => x => x;

// external
Unit = %self(u). Unit unit (%unroll u);
unit : Unit = %unroll unit;

Typing Self

Because self requires assuming self, there are a couple ways of typing it.

Unification

Use an unification engine and after typing the content unify it against itself.

Constraint

Accumulate all the clashes involved on the pending variable and check them afterwards.

Assume

Type the type without checking any of the types that depends on itself. Then type the type against the assumption and it should match.

%self(False). (f : %self(f). %unroll False f) -> Type

assume False (%self(False). _A);
  check ((f : %self(f). %unroll False f) -> Type) _A
    check (%self(f). %unroll False f) Type;
      assume f (%self(f). _B);
        check (%unroll False f) Type;
            // TODO: accumulate substitution inside of unroll, like in Coq
          check (%unroll False) (_C -> _D);
            unify _A (_C -> _D);
          check f _C;
            unify _C (%self(f). _B);
          unify _D Type
      unify _B (%unroll False f);
    check Type Type;
unify ((f : %self(f). %unroll False f) -> Type) ((f : %self(f). %unroll False f) -> Type)

Another Self

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

False = %fix(False) : (f : %self(f). False f) -> Type.
  f => (P : (%self(f). False f) -> Type) -> P f;
False = %self(f). False f;

Prop : Type
((A : Prop) -> (x : A) -> A) : Prop





fix%Unit
    (unit : %self(unit). (u : %self(u). Unit unit u) -> Unit unit u)
    (u : %self(u). Unit unit u) : Type
  = (P : (%self(u). Unit unit u) -> Type) -> P (unit u) -> P u;

%self(False). (f : %self(f). False f) -> Type

%self(False, f). (P : False -> Type) -> P f;

%self(Unit). (unit : %self(a). Unit a a) -> (%self(u). Unit unit u) -> Type



%self(Unit). (unit : %self(unit). (u : %self(u). Unit unit u) -> Unit unit u)
  (u : %self(u). Unit unit u) -> Type

%fix(Unit) : (A : Type) -> (unit : A -> A) -> (u : A) -> Type.
  A => unit => u => (unit : %self(A, unit). Unit A u u) -> (%self(u). Unit unit u) -> Type.


%fix(Unit) : (A : Type) -> Type.
  A => (wrap : A -> Unit A) -> (unit : Unit A) ->
  %self(A, u). (P : Unit A -> Type) -> P unit -> P (wrap u);

%self(A, u). (P : (%self(A, f). Unit A f) -> Type) -> P unit -> P (wrap u)

// False
Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

fix%Sigma A B
  (pair : %self(pair).
    (A : Type) -> (B : A -> Type) ->
    (x : A) -> (y : B x) -> Sigma A B pair (pair A B x y))
  (s : %self(s). Sigma A B pair s)
  = pair => s =>
    (P : (%self(s). Sigma A B pair s) -> Type) ->
    ((x : A) -> (y : B x) -> P (pair A B x y)) ->
    P s;

Unit = %self(Unit, u).
  (P : Unit -> Type) -> P (%fix(Unit, u). P => x => x) -> P u;
fix%unit : Unit unit = P => x => x;
Unit = Unit unit;

refl =>(%self(f : False). (P : False -> Type) -> P f) refl;
%fix(False).


A => x => (f : %self(A, f). False A f) -> Type

Γ, A : Type, x : B |- T : Type
------------------------------
%self(A, x : B). T : B[A := %self(A, x : B). T]


False = %self(A, f). False A f;

Why self?

A term that does induction of itself, is a term that must mention itself on the type level. As terms are proofs those must be described by some proposition aka a type. So we need a proposition that can manipulate it's own proof.

This is similar to how impredicative polymorphism allows for a proposition to mention the universe where it itself inhabits.

How can a type mentions it's own term?

Assume term on the context

Major issue here is that all terms must have a valid type in context. And the term has the same type as the proposition that is still not typed.

Some trick like Tarski universes

-----------
Self : Type

Γ |- M : Self
----------------
%typeof M : Type

Γ |- M : Self
----------------------
%unpack M : %typeof M

Γ, x : Self |- T : Type
-----------------------
%self(x). T : Type

Γ |- M : %self(A, x). T
-----------------------
%unroll M : T[A := %self(A, x). T | x := M]
False : %self(False). (f : %self(f). False f) -> Type;
False = f => (P : (%self(f). False f) -> Type) -> P f;
// close
False = %self(f). False f;


False : %self(False). (f : %self(f). False f) -> Type;
// False must be callable inside of False
// False must be callable with (%self(f). False f) inside of False

False : %self(False). (f : Self) -> Type;

False = (A : Type) => (f : A) => (P : A -> Type) -> P f;
False = %self(A, f). (P : A -> Type) -> P f;

Unit = X => (unit : X) =>
  %self(A, u). (P : (A : Type) -> (u : A) -> Type) -> P X unit -> P A u;
unit
  : %self(X, unit).  (P : (A : Type) -> (u : A) -> Type) -> P X unit -> P X unit
  = %fix(X, unit). (P : (A : Type) -> A -> Type) => (x : P X unit) => x;

%unroll unit : %self(A, u). (P : (A : Type) -> (u : A) -> Type) ->
  P (%self(X, unit).  (P : (A : Type) -> (u : A) -> Type) -> P X unit -> P X unit) unit ->
  P A u

Unit = Unit (%self(X, unit). Unit X unit) unit;

unit : %self(X, unit). Unit X unit
%unroll unit : Unit (%self(X, unit). Unit X unit) unit


%self(A, u). (P : (A : Type) -> A -> Type) ->
  P (%self(X, unit). Unit X unit) unit -> P A u

(P : (A : Type) -> A -> Type) ->
  P (%self(X, unit). Unit X unit) unit -> P A u
unit : Unit = %unroll unit;

%self(Unit).
  (unit : %self(a). Unit a a) ->
  (u : %self(u). Unit unit u) -> Type


False = (f : Self) -> ()
False = %self(f). False f;
Self (x => )


%typeof M : %self(False). (f : %self(f). False f) -> Type

%self(Unit).
  (unit : %self(a). Unit a a) ->
  (u : %self(u). Unit unit u) -> Type

%fix
%self(Unit).

fix%Unit (u : Self) (unit : %typeof u) =
  (P : (%self(u). %typeof u) -> Type) -> P unit -> P (%unpack u);

unit : %self(unit). Unit unit (%valueof unit) = _;

Unit = %self(u). Unit u unit;


Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

Γ, A : Type, x : A |- M : T
------------------------------
%fix(A, x). M : %self(A, x). T

Γ |- M : %self(A, x). T
-------------------------------------------
%unpack M : T[A := %self(A, x). T | x := M]

Γ |- M : %self(A, x). T
-------------------------------------------
%unfold M : T[A := %self(A, x). T | x := M]

Bool = T => (true : T) => F => (false : F) => %self(Bool, b).
Bool = T => (true : T) => F => (false : F) => %self(Bool, b).
  (P : (A : Type) -> A -> Type) -> P T true -> P F false -> P Bool b;

// internal
UnitT = %self(Unit, u). (P : (A : Type) -> A -> Type) -> P Unit u -> P Unit u;
unit : UnitT = %fix(Unit, u). (P : (A : Type) -> A -> Type) => (x : P Unit u) => x;

Unit T (unit : T) (u : T) =
  (P : T -> Type) -> P unit -> P (w Unit u);

fix%UnitW =
  Unit UnitW ? ()
unit_ind
  : (P : UnitT -> Type) -> P unit -> (u : Unit) -> P u
  = P => p_unit => u =>
    u (A => x => (A_eq_UnitT : A == UnitT) -> P (A_eq_UnitT (T => T) x))
     (A_eq_UnitT => )
// external

unit : Unit = %unroll unit;

%self(Unit, u).
  (P : (A : Type) -> A -> Type) -> P U unit -> P Unit u
(P : (A : Type) -> A -> Type) -> P U Unit -> P Unit U

Bool = T => (true : T) => F => (false : F) => %self(Bool, b).
  (P : (A : Type) -> A -> Type) -> P T true -> P F false -> P Bool b;
true
  : (F : Type) -> (false : F) -> %self(T, true). Bool T true F false
  = F => false => %fix(T, true).
    (P : (A : Type) -> A -> Type) => (then : P T true) => (else : P F false) => then;
false
  : %self(F, false). Bool (%self(T, true). Bool T true F false) true F false
  = %fix(F, false).
    (P : (A : Type) -> A -> Type) => (then : P T true) => (else : P F false) => else;
Bool = Bool
  (%self(T, true). Bool T true (%self(F, false). Bool T true F false) false) (true false)
  (%self(F, false). Bool T true F false) false;

// setup
Bool : Type
true : Bool
false : Bool

Bool = %self(A, b). (P : (A : Type) -> A -> Type) -> P Bool true -> P Bool false -> P A b;
true = (P : (A : Type) -> A -> Type) => (then : P Bool true) => (else : P Bool false) => then;
false = (P : (A : Type) -> A -> Type) => (then : P Bool true) => (else : P Bool false) => else;

Letsch

------------------------------------
(x : Bool) => x : (x : Bool) -> Bool

-------------------------------------------------
(A : Type) => (x : A) => x : (A : Type) -> A -> A

------------------------------
(A : Type) => A : Type -> Type

Bool = (A : Type) -> A -> A -> A;

------------------------------------------------------
  (b : Bool) => (x : b Type Int String) => x
: (b : Bool) -> b Type Int String -> b Type Int String


Nat = (A : Type) -> A -> (A -> A) -> A;
ind : (P : Nat -> Type) -> P zero ->
  ((n : Nat) -> P n -> P (succ n)) -> (n : Nat) -> P n = ?;

f zero (p_zero) : P (succ zero)


case : (b : Bool) -> (A : Type) -> A -> A -> A = _;
ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b = _;
Bool = (P : Bool -> Type) -> P true -> P false -> P b?;

Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

Γ, A : Type, x : A |- M : T
------------------------------
%fix(A, x). M : %self(A, x). T

Γ |- M : %self(A, x). T
-------------------------------------------
%unroll M : T[A := %self(A, x). T | x := M]

False = %fix(False). %self(f). (P : False -> Type) -> P f;

(P : Nat ->)

Identity Induction

fix%Unit (unit : %self(unit). Unit unit unit) (u : %self(u). Unit unit u) : Type
  = (P : (%self(u). Unit unit u) -> Type) -> P unit -> P u;
fix%unit : Unit unit unit =
  (P : (%self(u). Unit unit u) -> Type) => (x : P unit) => x;
// keeping induction clean

%self(False). (f : %self(f). False f) -> Type
%self(Unit). (unit : %self(a). Unit a a) -> (%self(u). Unit unit u) -> Type

Γ, A : Type, x : A |- M : T
------------------------------
%fix(A, x) : T. M : %self(A, x). T

(unit : %self(a). Unit a a)

Unit => %self(U, u). Unit U u u;

%self(False). (f : %self(f). False f) -> Type

%self(False). (A : Type) -> (f : %self(f). False f) -> Type

FalseT (ExternallyApply : (A : Type) -> A -> (((A : Type) -> A ->) -> Type) -> Type) =
  %self(T, False). ExternallyApply T False
      (False => A ->(f : %self(A, f). False A f) -> Type);

FalseT (T => False => A => f => )

fix%UnitT U1 (unit : U1) U2 (u : U2) =
  (unit : %self(U, u). UnitT U u U u) ->
  (u : %self(U, u). UnitT _ unit U u) ->
  Type;
fix%Unit
  (unit : %self(U, u). UnitT U u U u) U (u : U) : Type
  = (P : (%self(U, u). Unit unit U u) unit U u) ->
    Type) -> P unit -> P u;
fix%unit

%fix(A, Unit) : UnitT A Unit.
  unit => u => (P : )

Unit = fix(A, Unit) : (unit : Unit) -> (u : Unit) -> Type.
  (P : Unit unit u -> Type) -> P unit -> P u;

fix%Unit Unit (unit : Unit) U (u : U) : Type =
  (P : );
False = A => f =>
  (f : %self(A, f). False A f) -> Type;

False = A => f => False False




Unit =
  (unit : %self(a). Unit a a) -> (%self(u). Unit unit u) -> Type

False = A => (f : A) =>
  (P : A -> Type) -> P f
False = %fix(False) : (f : %self(f). False f) -> Type.
  f => (P : (%self(f). False f) -> Type) -> P f;
False = %self(f). False f;

UnitT = %self(Unit, u). (P : (A : Type) -> A -> Type) -> P Unit u -> P Unit u;
unit : UnitT = %fix(Unit, u). (P : (A : Type) -> A -> Type) => (x : P Unit u) => x;


Unit : Type
unit : Unit

Unit = (P : Unit -> Type) -> P unit -> P unit;

History

Internal Fix and Self

Unit : Type
unit : Unit;

Unit = %self(u). (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;

// expanded
Unit = %fix(Unit). (
  unit = %fix(unit). (P : Unit -> Type) => (x : P unit) => x;
  %self(u). (P : Unit -> Type) -> P unit -> P u
);

No Internal Expansion of Fix

False = %fix(False). %self(f). (P : False -> Type) -> P f;

%fix(False). (P : False -> Type) -> P f

Unit : %self(Unit). (u : %self(u). Unit u). Type;
unit : %self(u). Unit u;

Unit = u => (P : (%self(u). Unit u) -> Type) -> P unit -> P u;
unit = (P : (%self(u). Unit u) -> Type) => (x : P unit) => x;


Unit = %self(Unit). (unit : %self(u). Unit u) ->

fix%Unit (unit : %self(u). Unit u u) (u : %self(u). Unit u u) :Type.
  (P : %self(u). Unit u u) -> P unit -> P u;
fix%unit : Unit unit unit = (P : %self(u). Unit u u) => (x : P unit) => x;

Unit = %self(u). Unit u u;
unit : Unit = unit;

unit : %self(u). Unit unit u;

%self(Unit).
  (u : %self(u). Unit unit u) ->
  (unit : %self(unit). Unit unit unit) -> Type



Unit : %self(Unit).

  (unit : %self(unit). (u : %self(u). Unit unit (unit u)) -> Unit unit (unit u)) ->
  (u : %self(u). Unit unit (unit u)) -> Type;

(u : %self(u). Unit unit (unit u)) -> Unit unit (unit u)

%self(unit). Unit unit (unit u)

expected : %self(u). Unit unit u
received :

Unit = %fix(Unit) : (unit : %self(unit). (u : ) Unit unit u) ->
  (u : %self(u). Unit unit u) -> Type.
  unit => u => (P : (%self(u). Unit unit u) -> Type) -> P unit -> P u;

// WARNING: is this type well formed??? (%self(u). Unit u u) is weird
Unit : %self(Unit). (unit : %self(u). Unit u u) -> (u : %self(u). Unit unit u) -> Type
unit : %self(u). Unit u u;

Unit = unit => u => (P : (%self(u). Unit unit u) -> Type) -> P unit -> P u;
unit = (P : (%self(u). Unit unit u) -> Type) => (x : P unit) => x;
// external
Unit = %self(u). Unit unit u;
unit : Unit = unit;

// expanded
Unit = %fix(Unit) : (unit : %self(u). Unit u u) -> (u : %self(u). Unit unit u) -> Type.
  unit => u => (P : (%self(u). Unit unit u) -> Type) -> P unit -> P u;
unit = %fix(unit) : Unit unit unit.
  (P : (%self(u). Unit unit u) -> Type) => (x : P unit) => x;
// external
Unit = %self(u). Unit unit u;
unit : Unit = unit;

No Implicit %unroll of %self

// WARNING: is this type well formed???
Unit : %self(Unit). (unit : %self(u). Unit u u) -> (u : %self(u). Unit unit u) -> Type
unit : %self(u). Unit u u;

Unit = unit => u => (P : (%self(u). Unit unit u) -> Type) -> P unit -> P u;
unit = (P : (%self(u). Unit unit u) -> Type) => (x : P unit) => x;
// external
Unit = %self(u). Unit unit u;
unit : Unit = unit;

Alternative Induction

Eq A x y = (P : A -> Type) -> P x -> P y;

Unit1 = %fix(Unit1). %self(u). (P : Unit1 -> Type) -> P u -> P u;
unit : Unit1 =
  %fix(u). (P : Unit1 -> Type) => (x : P u) => x;




(P : Unit -> Type) -> P unit -> P unit
(P : Unit -> Type) -> P unit -> P unit

unit     : %self(u). (P : Unit -> Type) -> P (%unroll u) -> P (%unroll u);

%unroll unit : %self(u). (P : Unit -> Type) -> P (%unroll u) -> P (%unroll u);
expected     : %self(u). (P : Unit -> Type) -> P (%unroll unit) -> P u


%self(Unit).
  (unit : %self(u). Unit u (%unroll u)) ->
  (u : %self(u). Unit unit (%unroll u)) -> Type



%unroll unit : %self(u). Unit u u
%unroll unit : %self(u). Unit (%unroll unit) u

fix%Unit (unit : %self(u). Unit u u) (u : %self(u). Unit unit u) : Type =
  (P : Unit -> Type) -> P

fix%Unit = %self(u). (K : Type) -> (Eq Unit u (%unroll unit) -> K) -> K;

fix%UnitT = %self(u). (K : Type) -> (Eq UnitT u u -> K) -> K;
fix%unit : UnitT = K => (k : (Eq Unit u u -> K)) => k refl;
fix%Unit = %self(u). (K : Type) -> (Eq Unit u (%unroll unit) -> K) -> K;

UnitT = %self(UnitT, u). (K : Type) -> (Eq UnitT u u -> K) -> K;
unit : UnitT = %fix(UnitT, u) => K => (k : Eq UnitT u u -> K) => k refl;



UnitT = %self(Unit, u). (K : Type) -> (Eq Type Unit Unit-> Eq Unit u u -> K) -> K;
unit : UnitT = %fix(Unit, u). (K : Type) => (k : Eq Unit u u -> K) => k refl;

Unit = %self(Unit, u). (K : Type) -> (Eq ->(P : (A : Type) -> A -> Type) -> P UnitT unit -> P Unit u;

ind (P : UnitT -> Type) (x : P Unit (%unroll unit)) (u : Unit) : P u =
  u (A => x => (eq : A == UnitT) -> P A x eq)

Unit T (unit : T) (u : T) =
  (P : T -> Type) -> P unit -> P (w Unit u);

Modern

%self(False). False // Type : Type

%self(A, False). False;

%self(A, False). (eq : A == ((eq : A == A) -> False)). eq (T => T) False;

%self(A, False). (eq : A == Type). eq (T => T) False;



Unit A unit u = (P : A -> Type) -> P unit -> P u;
unit = %fix(A, u) : Unit A u u. (P : A -> Type) => (x : P unit) => x;

Unit = %self(U2, u). Unit (%fix(U1, u). Unit U1 u U1 u) unit U2 u;


unit = (P : (%self(u). Unit u) -> Type) => (x : P unit) => x;


Unit U1 unit U2 u = (P : (A : Type) -> A -> Type) -> P U1 unit -> P U2 u;
U1 = %self(U1, u). Unit U1 u U1 u;
unit : U1 = %fix(U1, u). P => x => x;

Unit = %self(U2, u). Unit U1 unit U2 u;
// TODO: relies on removing duplicated self %self(A, x). %self(U2, u). T
unit = %unroll (A => x => %self(U2, u). Unit A x U2 u) unit;


Eq A x y = (P : A -> Type) -> P x -> P y;
refl A x : Eq A x x = P => x => x;

T1 = %self(T1, _). Eq Type T1 T1;
T2 = %self(T2, _). Eq Type T1 T2;

T2 = Eq Type
  (%self(T1, _). Eq Type (%self(T1, _). Eq Type T1 T1) T1)
  (%self(T1, _). Eq Type (%self(T1, _). Eq Type T1 T1) T1);

T2 = Eq Type (%self(T1, _). Eq Type (%self(T1, _). Eq Type T1 T1) T1) (%self(T1, _). Eq Type (%self(T1, _). Eq Type T1 T1) T);

T2 = Eq Type
  (%self(T1, _). Eq Type (%self(T1, _). Eq Type T1 T1) T1)
  (%self(T2, _). Eq Type (%self(T1, _). Eq Type T1 T1) T2);

// TODO: relies on removing duplicated self %self(A, x). %self(U2, u). T
unit = %unroll (A => x => %self(U2, u). Unit A x U2 u) unit;

Unit : Type;
T : (u : Unit) -> Type;
unit : Unit;

T = (u : Unit) => (P : Unit -> Type) -> P unit -> P u;
Unit = %self(u). T
%self(u). T
Unit = (unit : Unit) => (P : Unit -> Type) -> P unit


Unit U1 unit U2 u =
  (P : (A : Type) -> A -> Type) -> P U1 unit -> P U2 u;
U1 = %self(U1, u). Unit U1 u U1 u;
unit : U1 = %fix(U1, u). P => x => x;

Unit = %self(U2, u). Unit U1 unit U2 u;


%self(U2, u). Unit U1 unit U2 u === %self(U1, u). Unit U1 unit U1 u

Unit A unit u = (P : A -> Type) -> P unit -> P u;
U1 = %self(U1, u). Unit U1 u u;
unit : U1 = %fix(U1, u). P => x => x;

U2 = %self(U2, u). Unit U2 unit u;


Unit u unit = (P : (%typeof u) -> Type) -> P unit -> P (%valueof u);
U1 = %self(u). Unit u (%valueof u);
unit : %self(u). Unit u (%valueof u) = %fix(u). P => x => x;

unit : %self(u). Unit u unit = %unroll unit;
Unit = %self(u). Unit u unit;

%fix(A, Sigma).

Degenerate

Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

Γ, A : Type, x : A |- M : T
------------------------------
%fix(A, x). M : %self(A, x). T

Γ |- M : %self(A, x). T
-------------------------------------------
%unpack M : T[A := %self(A, x). T | x := M]

Γ |- M : %self(A, x). T
-------------------------------------------
%unfold M : T[A := %self(A, x). T | x := M]

loop = %fix(f : Unit -> Unit). (x : Unit) => f x;

loop = %fix(A, f). (unfold : A -> Unit -> Unit) => (x : Unit) => unfold f x;

Eq A x B y = (P : (T : Type) -> T -> Type) -> P A x -> P B y

l = %fix()
%self(A, f). (unfold : A -> Unit -> Unit) -> Unit -> Unit;

Fix = %fix(Fix) : Type. (f : Fix) -> Unit;
fix : Fix = (f : Fix) => f f;


Fix = %fix(A, Fix).
  (unfold : A -> Type) -> (f : unfold Fix) -> Unit;
fix = (f : Fix) => f ((x : Fix) => x);


Loop = %fix(Loop) : Type -> Type -> Type. A => B => A -> Loop B A;

Loop = %fix(A, Loop). A => B =>
Loop = %fix(A, Loop).
  (unfold : A -> ) => A => B => A -> unfold Loop B A


fix = (f : Fix) => f f;

%self(Fix, _). (f : Fix) -> Unit


False = (f : Loop refl) => f refl;

Loop = %fix(A, Loop). (unfold : A -> Type) -> (f : Unit) -> unfold Loop;
False = (f : Loop) => f (x => x) () (x => x) ();

Γ, A : Type, x : A |- M : T
------------------------------
%fix(A, x). M : %self(A, x). T

Fix = %fix(A, Fix). (unfold : A -> Type) => unfold Fix -> Unit;
fix = (f : Fix) => f (x => x) f;

False0 = %fix(A, False). (eq : A == Type) -> (f : eq (T => T) False) -> Unit;
False1 : Type = %unfold False;



%self(False). (f : %self(f). False f) -> Type
%fix(False) : (f : %self(f). False f) -> Type.
  f => (P : (%self(f). False f) -> Type) -> P f;


//
Unit : %self(Unit). (u : %self(u). Unit u) -> Type;
unit : %self(u). Unit u;

Unit = u => (P : (%self(u). Unit u) -> Type) -> P unit -> P u;
unit = (P : (%self(u). Unit u) -> Type) => (x : P unit) => x;

// steps, define both types, define Unit, define unit using definition of Unit

TUnit = %self(Unit). (u : %self(u). Unit u) -> Type;

MUnit (Unit : TUnit) (unit : Tunit Unit) =
  u => (P : (%self(u). Unit u) -> Type) -> P unit -> P u;
Munit (Unit : TUnit) (unit : Tunit)
  = (P : (%self(u). Unit u) -> Type) => (x : P unit) => x;



expected : %self. \2 \1 \0
received : %self. \1 (%unroll \0) \0
expected : %self(u/1). Unit u/2 u/1
received : %self(u). Unit u u
//
(let ((fs (Y* ((f1 f2 ... fn) => e1) ... ((f1 f2 ... fn) => en))))
    (apply ((f1 f2 ... fn) => e) fs))
Y (T : %self(T). (x : %self(x). T x) -> Type)
  (w : (x : %self(x). T x) -> T x) : %self(x). T x = %fix(x) : T x. w x
Y* l =
  (u => (u u))
  (p => (map (li => x => li (p p) x) l))

fs = (Y* ((f1 f2 ... fn) => e1) ... ((f1 f2 ... fn) => en));
(apply ((f1 f2 ... fn) => e) fs))

%self(Unit). (unit : %self(u). Unit u u) -> (u : %self(u). Unit unit u) -> Type

// dependencies
Unit = %fix(Unit) : (u : %self(u). Unit u) -> Type.
  u => (P : (%self(u). Unit u) -> Type) -> P unit -> P u;

UnitT = %self(Unit). (u : %self(u). Unit u) -> Type;


Unit2 = %fix(Unit) : (unit : %self(u). Unit u) -> UnitT.
  unit => MUnit (Unit unit) unit;

UnitX = %fix(Unit) : (unit : %self(u). Unit u) -> UnitT.
  unit => (u : %self(u). Unit u) => (P : (%self(u). Unit u) -> Type) -> P unit -> P u) (Unit unit) unit;



Unit = (unit : %self(u). Unit u) =>
  %fix(Unit) : (u : %self(u). Unit u) -> Type. MUnit Unit

T1 = %self(u). Unit u u;

%self(Unit).
  (unit : %self(u). Unit u u) ->
  (u : %self(u). Unit unit u) -> Type

expected : %self(u). Unit unit u
received : %self(u). Unit u u
Unit =

(f => x => f x x)

(x : Int 2) => x + x;

(G : Grade) -> Type;

(x : $Int) => (p : Bool)
  (p | true => x + 1
    | false => x) x;


f = (x : Int 2) => x + x;

abs : (A : Type) -> A = ?;

%self(Unit).
  (self%unit : %self(u). Unit unit u) ->
  (self%u : Unit unit u) -> Type

%self(False). (f : %self(f). False f) -> Type;

%self(T, False).
  (unfold_T :
    %self(UT, _). T -> (unfold_T : UT) -> (f : ) -> Type) ->
  (f : %self(A, f). (unfold_A : A == ?) ->
    unfold_T False unfold_T (unfold_A f)) -> Type

%self(False). (f : %self(f). False f) -> Type;

Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

A = Γ, x : A |- T : Type  A == T
----------------------------
Γ |- %self(x). T : Type



%exists ?X. %self(False) : (f : %self(f). _) -> Type.
  (f : %self(f). False f) -> Type;

((A : Type 0) -> A -> A) : Type 1;

Type : Type

x => x;

id : (0 A : Prop) -> A -> A = A => x => x;

x = id ((0 A : Prop) -> A -> A);

1234567890
!@#$^&*()_

(x => ())

Γ, x : %self(x). T |- T : Type
------------------------------
Γ |- %self(x). T : Type

Γ, x : %self(x). T |- M : T
-----------------------------
Γ |- %fix(x). M : %self(x). T

case : Bool -> (A : Type) -> A -> A -> A = _;
Bool = (A : Type) -> A -> A -> A;

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b = _;

Unit : %self(Unit). (unit : %self(unit). %self(u). Unit unit u) -> (u : %self(u). Unit unit u) -> Type;
  unit :%self(unit). %self(u). Unit unit u
  u : %self(u). Unit unit u;

Unit : %self(Unit). _A

%self(False). (f : %self(f). False f) -> Type

False : %self(False). _A
  f : %self(f). _B
    _A := (f : %self(f). _B) -> Type
  _B := False f
unify (%self(False). _A) (%self(False). (f : %self(f). False f) -> Type)
unify (%self(False). (f : %self(f). False f) -> Type) (%self(False). (f : %self(f). False f) -> Type)


Unit : %self(Unit). (unit : %self(unit). %self(u). Unit unit u) -> (u : %self(u). Unit unit u) -> Type;
%self(Unit). (unit : %self(unit). %self(u). Unit unit u) -> (u : %self(u). Unit unit u) -> Type;

Bool = %self(b). (P : Bool -> Type) -> P true -> P false -> P b;

(x => x(x))(x => x(x))
(x => x(x))(x => x(x))
(x => x(x))(x => x(x))

f () = f ()
f = (x => x(x));
g = (x => x(x));

true_ = x => y => x;
false_ = x => y => y;

if_ = b => x => y => b(x)(y);

if_(true_)(0)(1)

Kind =
  | *
  | K -> K;
Type =
  | A -> B
  | <A : K>B
  | A<B>;

Term =
  | x
  | (x : T) => m
  | m n
  | <A>m;
  | m<A>;

id : (x : Int) -> Int = (x : Int) => x;
incr : (x : Int) -> Int = (x : Int) => x + 1;

zero = z => s => z;
succ = n => z => s => s(n(z)(s));

one = z => s => s(z);
two = z => s => s(s(z));

two = succ(succ(zero));
Bool = <A>(x : A) => (y :)
true : = x => y => x;
false : = x => y => y;
(x : Int) -> Int
Int implies Int;

<A>(x : A) -> A

<A>(x : A) => A;

Forall A, A implies A;

(<A>(x : A) -> A)<Int>

(x => m)(n) === m[x := n];
(<A>m)<B> === m[A := B];

(<A>(x : A) => x)<Int>
((x : A) => x)[A := Int]
(x : Int) => x

(x : Int) =>

(x : Int) =>
(<A>((x : A) => x))<Int>

Int : *
(<F : * -> * >F<Int>)


T : * -> *

Term -> Term // Simply Typed Lambda Calculus // Functions
Type -> Term // System F // Parametric Polymorphism
Type -> Type // System Fω // Higher Kinded Type
Term -> Type // Calculus of Construction // Dependent Types


Id : Type = (A : Type) -> A -> A;
id : Id = (A : Type) => (x : A) => x;

Bool = (A : Type) -> A -> A -> A;
true : Bool = (A : Type) => (x : A) => (y : A) => x;
false : Bool = A => x => y => y;

A -> B

f : (x : Bool) -> x Type Int String -> x Type Int String
  = (x : Bool) => (y : x Type Int String) => y;

f : (x : Bool) -> x Type Int String -> x Type Int String
  = (x : Bool) => (y : x Type Int String) => y;

a : Int -> Int = f true;
b : String -> String = f false;


| Rust |
| OCaml | TypeScript |
| Elixir | Haskell | C# | C | Python | Lua |
| Scala | F# | Go | Java | PHP | Clojure | Ruby | JavaScript | C++ | Perl |

@Unit -> (unit : @unit -> @u -> (@Unit) unit u) -> (u : @u -> (@Unit) unit u) -> Type
@(Unit : @Unit -> (unit : @unit -> @u -> (@Unit) unit u) -> (u : @u -> (@Unit) unit u) -> Type) =>
  (unit : @unit -> @u -> (@Unit) unit u) => (u : @u -> (@Unit) unit u) =>
  (P : (u : @u -> (@Unit) unit u) -> Type) -> P (@unit) -> P u


@(False : @False -> (f : @f -> False@ f) -> Type) => (f : @f -> False@ f) => (P : (f : @f -> False@ f) -> Type) -> P f

@A : (f : @f -> @A f) -> Type


f : expected = term : received

term : expected

unit = %fix(unit).

  %fix(u) : (eq :
    %self(eq).
      (P : Unit (unit u eq) (u eq) -> Type) -> P (unit u eq) -> P (u eq);
  ) -> Unit (unit u eq) (u eq).
    (P : (%self(u). Unit (unit u eq) u) -> Type) => (x : P (unit u eq)) =>
      eq P x;


%self(unit). %self(u). Unit unit u;

expected : %self(u). Unit unit u
received : %self(u). () -> Unit unit (u ())

%fix(unit) : -> W (%self(u). Unit unit u).
  %fix(u) : (self%eq : unit u eq == u eq) -> Unit (unit u eq) (u eq).
    eq =>  (P : (%self(u). Unit (unit u eq) u) -> Type) => (x : P (unit u eq)) => eq P x;


%self(Unit).
  (unit : %self(unit). %self(u). Unit unit u) ->
  (u : %self(u). Unit unit u) -> Type;

%self(Unit).
  (unit : %self(unit) Unit unit unit) ->
  (u : %self(u). Unit unit u) -> Type;

// TODO: those should be equal
%self(unit). %self(u). Unit unit u ===
%self(unit). Unit unit unit


Γ |- M : T[x := M]
-------------------------------
%roll(M) <== %self(x). T

Γ |- M : %self(u : A). B
-------------------------------
%unroll(M) : B[u := %unroll(M)]

Γ |- M : A
-------------------------------
M@ <== %self(x). B

%self(x). Int <> Int


T : %self(T). (a : %self(b). T b b) -> (c : %self(d). T a d) -> Type;

%self(T). (e : %self(f). T f f) -> (g : %self(h). T a d) -> Type


// %self(unit). %self(u). Unit unit u

CoC + Self Types


%self(Unit).
  (unit : %self(unit). %self(u). Unit unit u) ->
  (u : %self(u). Unit unit u) -> Type;

(unit : %self(unit). %self(u). Unit unit u) => Unit unit unit

%self(Unit).
  (unit : %self(unit) Unit unit unit) ->
  (u : %self(u). Unit unit u) -> Type;


data%Bool = | true | false;
data%Nat = | zero | succ (n : Nat);


Type : Type

// functions

Γ, x : A |- B : Type
--------------------
(x : A) -> B : Type

Γ, x : A |- m : B
---------------------------
(x : A) => m : (x : A) -> B

Γ |- m : (x : A) -> B   Γ |- n : A
----------------------------------
m n : B[x := n]

// induction

Γ, x : @x -> T |- T : Type
----------------------
@x -> T : Type

Γ, x : @x -> T |- m : T
-----------------------
@x : T => m : @x -> T

%self(Unit). (unit : %self(unit). Unit unit (%coerce unit : %self(u). Unit unit u)) ->
  (u : %self(u). Unit unit (%coerce u : %self(u). Unit unit u)) -> Type;

%self(Unit). (a : %self(b). Unit b (%coerce b : %self(u). Unit b u)) ->
  (c : %self(d). Unit a (%coerce d : %self(u). Unit a u)) -> Type;

received : %self(a). Unit b a
expected : %self(a). Unit b (%coerce a : %self(u). Unit b u)

%self(Unit).
  (u : %self(u). Unit (%coerce (%unroll u))) -> Type;

fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u) =
  (P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u) =
  (P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%False (f : %self(f). False f) =
  (P : (%self(f). False f) -> Type) -> P f;

Unit = unit => %fix(Unit). (u : %self(u). Unit u) =>
  (P : (%self(u). Unit u) -> Type) -> P unit -> P u;

Unit = unit => u => %fix(Unit).%self(u). (P : ? -> Type) -> P unit -> P u;

%self(u). (%fix(Unit). (unit : %self(unit). Unit unit) =>
  (P : Unit unit -> Type) -> P unit -> P u) (%fix(unit). P => x => x);

%self(Unit). (unit : %self(unit). Unit unit (%unroll unit)) ->
  (u : Unit unit (%unroll unit)) -> Type;

fix%Unit (unit : %self(unit). Unit unit (%unroll unit)) (u : Unit unit (%unroll unit)) =
  (P : Unit unit (%unroll unit) -> Type) -> P (%unroll unit) -> P u;
fix%unit : Unit unit (%unroll unit) =
  (P : Unit unit (%unroll unit) -> Type) => (x : P (%unroll unit)) => x;

%self(Unit). (unit : %self(unit). Unit unit (%unroll unit)) ->
  (u : Unit unit (%unroll unit)) -> Type;


W u == (P : (%self(u). W u) -> Type) -> P unit -> P unit



Unfold (Unit : Type) (unit : Unit) =
  %self(I). (%self(u). (P : Unit -> Type) -> P unit -> P (I u)) -> Unit;

MKUnit (Unit : Type) (unit : Unit) (I : Unfold Unit unit) =
  %self(u). (P : Unit -> Type) -> P unit -> P (I u);
fix%Unit
  (unit : %self(unit). (unfold : %self(unfold). Unfold (Unit unit unfold) (%unroll unit)) -> Unit unit unfold)
  (unfold : %self(unfold). Unfold (Unit unit unfold) (%unroll unit))
  = MKUnit (Unit unit unfold) ((%unroll unit) unfold) unfold;


fix%Unit0
  (I : %self(I). (unit : %self(unit). Unit0 I unit) ->
    (%self(u). (P : Unit0 I unit -> Type) -> P (%unroll unit) -> P (I unit u)) -> Unit0 I unit)
  (unit : %self(unit). Unit0 I unit)
  = %self(u). (P : Unit0 I unit -> Type) -> P (%unroll unit) -> P (I unit u);

fix%Unit0
  (I : %self(I). (unit : %self(unit). Unit0 I unit) ->
    (%self(u). (P : Unit0 I unit -> Type) -> P (%unroll unit) -> P (I unit u)) -> Unit0 I unit)
  (unit : %self(unit). Unit0 I unit)
  = %self(u). (P : Unit0 I unit -> Type) -> P (%unroll unit) -> P (I unit u);
Unit1 = Unit0 (%fix(I). unit => x => x);

unit => (P : Unit1 unit -> Type) => (x : P (%unroll unit)) => I P x

unit = %fix(unit). %fix(u). (P : Unit1 unit -> Type) => (x : P (%unroll u)) => (x : P u)



%self(unit). %self(u). (P : Unit1 unit -> Type) -> P (%unroll unit) -> P u

%self(unit). %self(u). (P : Unit0 I unit -> Type) -> P (%unroll unit) -> P u

fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u)
  = (P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;


(P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P (%unroll unit)


MKUnit = (Unit : Type) => (unit : Unit) =>
  (unfold : %self(unfold). (%self(u). (P : Unit -> Type) -> P unit -> P (unfold u)) -> Unit) =>
  %self(u). (P : Unit -> Type) -> P unit -> P (unfold u);

fix%Unit (unit : %self(unit). Unit unit) = MKUnit (Unit unit) unit

fix%Unit0 =
Unit = MK (%self(u). Unit

%self(unit).

fix%unit
  : (P : (%self(u). W u) -> Type) -> P unit -> P unit
  = P => x => x;
fix%Unit (u : %self(u). Unit u) =
  (P : (%self(u). Unit u) -> Type) -> P (
    %fix(unit) : (P : (%self(u). Unit u) -> Type) -> P (%fix(unit). unit ) -> P u. unit
  ) -> P u;

Unit = %self(u). Unit i (%unroll u);
unit : Unit = unit;


u : %self(u). (%fix(Unit). (unit : %self(unit). Unit unit) =>
  (P : Unit unit -> Type) -> P unit -> P u) (?);


u : %self(u). (P : ((%fix(Unit). (unit : %self(unit). Unit unit) =>
  (P : Unit unit -> Type) -> P unit -> P u)) (%fix(unit). P => x => x) -> Type) -> P (%fix(unit). P => x => x) -> P u ;


%self(unit). Unit unit (%unroll unit);

received : %self(unit). %self(u). Unit unit u
expected : %self(unit). %self(u). Unit unit u

%self(u). Unit unit (%roll u)


%self(Unit). (unit : %self(unit). Unit unit (%coerce unit : %self(u). Unit unit u)) ->
  (u : %self(u). Unit unit u) -> Type;

received : %self(unit). Unit unit (%coerce unit : %self(u). Unit unit u)
expected : %self(u). Unit unit u
(unit : %self(unit). %self(u). Unit unit u) -> Unit unit (%unroll unit)

f = (unit : %self(unit). %self(u). Unit unit u) =>
  (P : (%self(u). Unit unit u) -> Type) => (x : P (%unroll unit)) => x;



%fix(unit). f unit



%self(unit). Unit (%coerce unit) unit;

received : Unit (%coerce unit) unit
expected : Unit unit unit

fix%unit : Unit (%roll unit) unit

%self(Unit). (unit : %self(unit). Unit unit unit) ->
  (u : %self(u). Unit unit u) -> Type
fix%Unit (unit)

main = print("Hello World");

fun x.
all x.

self x.
fix x.

((x : Int) => x)
((x : String) => x)

m : Nat -> Type
n : Int -> Type
(m x)
(n (coerce x))


fix%Fix = Fix -> Fix;

(a : Nat 1) => (b : Nat 1) => Nat 1
(x) => x + x
(f : Fix * 4) => f f;

(1 obj) =>

Induction Again

fix%False (I : %self(I). (%self(f). (P : False I -> Type) -> P (I f)) -> False I)
  = %self(f). (P : False I -> Type) -> P (I f);
False = False (%fix(unfold). (x ) => (x));

I : %self(I). (unit : %self(unit). (I : ?)  Unit1 unit I unit) -> %self(u). Unit0 I u;

Unit0T (T : Type) = %self(Unit0).
  (I : T -> %self(u). Unit0 I u) -> (u : %self(u). Unit0 I u) -> Type;

%self(Unit1). (unit : %self(unit). (I : %self(I). Unit1 unit I unit -> %self(u). Unit1 unit I u) -> Unit1 unit I unit) ->
  %self(Unit0). (I : ? -> %self(u). Unit0 I u) -> (u : %self(u). Unit0 I u) -> Type;

Unit0 (Unit : Type) (unit : Unit) (u : Unit) =
  (P : Unit -> Type) -> P unit -> P u;

%fix(Unit). (unit : %self(unit). Unit unit unit) => (u : %self(u). Unit unit u) =>

%self(False). (f : %self(f). False (%coerce f : ?)) -> Type;

%self(False). (f : %self(f). False (%coerce f : ?)) -> Type;

%self(f). False (%coerce f : %fix(T). %self(f). False (%coerce f : T))

%self(Unit). (
  (u : %self(u). Unit unit u)
)
%fix(Unit). (unit : %self(unit). Unit unit (%coerce unit : )) =>
  (u : %self(u). Unit unit u) =>
%fix(Unit2). unit => %fix(Unit1). u =>
  Unit0 ? unit u;

%fix(Unit2). (unit : %self(unit). (I : IT) -> Unit2 unit I (unit I)) =>
  %fix(Unit1). (I : %fix(IT). %self(I). (%self(unit). (I : IT) -> Unit2 unit I (unit I)) -> %self(u). Unit1 I u) =>
  (u : %self(u). Unit1 I u) => Unit0 (%self(u). Unit1 I u) (I unit) u;

fix%unit1 : Unit1 unit0 unit0 =
  (P : )
fix%Unit1 (Unit : Type) (unit : Unit) (I : %self(I). Unit -> %self(u). Unit1 Unit unit I u)
    (u : %self(u). Unit1 Unit unit I u) : Type =
  Unit0 (%self(u). Unit1 Unit unit I u) (I unit) u;

Unit1 (Unit : Type) (unit : Unit)
    (I : %self(I). (%self(u). Unit0 Unit unit (I u)) -> Unit) : Type =
  %self(u). Unit0 Unit unit (I u);

fix%Unit2 (unit : (I : ?) -> %self(unit). Unit0 (Unit2 unit))
  = Unit1 (Unit2 unit I) (unit I)

Unit1 (Unit : Type) (unit : Unit)
    (I : %self(I). (Unit0 Unit unit (I u)) -> Unit) : Type =
  Unit0 Unit unit (I u);

fix%Unit2 (unit : %self(unit). Unit1 unit I) (I : %self(I). Unit -> %self(u). Unit1 Unit unit I u)
    (u : %self(u). Unit1 Unit unit I u) : Type =
  Unit0 (%self(u). Unit1 Unit unit I u) (I unit) u;

%fix(Unit1). (I : %self(I). ? -> %self(u). Unit1 I u) => (u : %self(u). Unit1 I u) =>
  Unit0 (%self(u). Unit1 I unit u) (I unit) u;

fix%Unit0 (Unit : Type) (I : %self(I). Unit -> %self(u). Unit0 Unit I unit u)
  (unit : Unit) (u : %self(u). Unit0 Unit I unit u)
  = (P : (%self(u). Unit0 Unit I unit u) -> Type) -> P (I unit) -> P u;
fix%Unit1
  (I : %self(I). (%self(u). Unit1 I u) -> %self(u). Unit0 Unit I unit u)
  (unit : %self(unit). Unit1 I unit)
  = %self(u). Unit0 (%self(u). Unit1 I u) I unit u;

expected : %self(u). Unit0 Unit I unit u
fix%Unit1 (Unit : Type) (unit : Unit)
  (I : %self(I). Unit -> %self(u). Unit0 I u) (u : %self(u). Unit0 I u)
  = (P : (%self(u). Unit0 I u) -> Type) -> P (I unit) -> P u;

%fix(Unit1). (unit : %self(unit). (I : ? -> %self(u). Unit1 unit I u) -> Unit1 unit I unit) =>
  %fix(Unit0 : Unit0T). I => u =>
   (P : (%self(u). Unit0 I u) -> Type) -> P (I unit) -> P u;
Unit1 = Unit0 (%fix(I). unit => x => x);

(x => z) => x;


fix%False (I : %self(I). (%self(f). (P : False I -> Type) -> P (I f)) -> False I)
  = %self(f). (P : False I -> Type) -> P (I f);
False = False (%fix(I). x => x);

received : %self(unit). %self(u). (P : Unit I -> Type) -> P (I (%unroll unit)) -> P (I u)
expected : %self(u). (P : Unit I -> Type) -> P (I (%coerce unit)) -> P (I u)

%self(unit). %self(u). (P : Unit I -> Type) -> P (I (%unroll unit)) -> P (I u)

Unit0 (Unit : Type) (unit : Unit) (u : Unit) =
  (P : Unit -> Type) -> P unit -> P u;

%self(u). (I1 : -> T) ->
  (I0 : %self(I0). -> T) ->
  Unit0 T (I1 unit) (I0 u))
%fix(u). (P : T -> ) => ()

%self(Unit). (I : %self(I). ((
  unit : %self(unit). (P : Unit I -> Type) -> P (I unit) -> P (I unit) = _;
  %self(u). (P : Unit I -> Type) -> P (I unit) -> P (I u)
) -> Unit I))
 -> Type;

fix%Unit (I : %self(I). (%self(u). (P : Unit I -> Type) ->
  P (I (%fix(unit) : (P : Unit I -> Type) -> P (I unit) -> P (I unit). P => x => x)) -> P (I u)
) -> Unit I)
  = %self(u). (P : Unit I -> Type) ->
    P (I (%fix(unit) : (P : Unit I -> Type) -> P (I unit) -> P (I unit). P => x => x)) -> P (I u);

fix%Unit (I : %self(I). (u : %self(u). Unit I u) -> Unit I u) (u : %self(u). Unit I u) =
  (P : (%self(u). Unit I u) -> Type) -> P (%fix(u) : Unit I u. I (P => x => x)) -> P u;

%fix(u). (I : %self(I). ) =>
  (P : (%self(u). Unit I u) -> Type) => (x : P u) => (x : P u)

Unit1 = Unit (%fix(I). u => k => (x : P (%fix(u) : Unit I u. I u)) => ?)

fix%Unit (I : %self(I). (u : %self(u). Unit I u) -> Unit I u) (u : %self(u). Unit I u) =
  (P : (%self(u). Unit I u) -> Type) -> P (%fix(u) : Unit I u. I u) -> P u


Unit1 = Unit (%fix(I). u => P => (x : P (%fix(u) : Unit I u. I u)) => ?)

(P : (%self(u). Unit I u) -> Type) -> P (%fix(u) : Unit I u. I (%fix(unit). P => x => x)) -> P unit

False = False (%fix(I). x => x);

Ideas

This tries to avoid internal expansion of fixpoint but still achieve induction for Unit.

Simple External

Fails to type check due to some weird behaviour.

%self(Unit). (unit : %self(unit). Unit unit unit) =>
  (u : %self(u). Unit unit u) -> Type

Internal Fixpoint

fix%Unit (I : ?) (u : %self(u). Unit I u) =
  (P : (%self(u). Unit I u)) -> P (%fix(u) : Unit I u. I u) -> P u;

External Unfold

How to scale this to unit?

fix%False (I : %self(I). (%self(f). (P : False I -> Type) -> P f) -> False I) =
  %self(f). (P : False I -> Type) -> P f;
False = False (%fix(I). x => x);

Nested Self

How to build the constructor?

%self(Unit). (unit : %self(unit). %self(u). Unit unit u) ->
  (u : %self(u). Unit unit u) -> Type

Two Fixpoint

Seems natural if you try to lift first u then unit.

%self(Unit1). (unit : ?) -> %self(Unit0). (u : ?) -> Type

Trying Again the Fancy One

%fix(Rec). Rec -> ();

RecT = %self(RecT, Rec). (I : %self(B, I). B -> RecT -> Type) -> Type;
Rec : RecT = %fix(A, Rec). I => I I Rec -> ();

I = %fix(B, I). (I : B) => (Rec : RecT) => Rec I;


%fix(False). (f : False) => (P : False -> Type) -> P f
False = %fix(FalseT)

(Rec I -> ());

%self(False). (f : %self(f). False f) -> Type;

%self(FalseT, False).
  (I : %self(IT, _). FalseT -> (f : ?) -> Type) ->
  (f : %self(fT, f). I False I) -> Type;

Decomposing

Why does this works?

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

Γ, x : A |- B : Type  A === B[]
----------------------------------
%self(x : A). B : Type

Γ, x : A |- B : Type  A === B[x := ]
--------------------------------------------------
%self(x : A). B : Type

%self(False). (f : %self(f). False f) -> Type
%self(KFalse, False : (f : %self(Kf, f). KFalse f)).
  (f : %self(f). False f) -> Type

T : Type = %fix(False : Type). (f : False) -> (P : False -> Type) -> P f;

%fix(False : T). (f : False) ->
  (P : False -> Type) -> P
%self(T, False). (I : T -> Type) -> (f : I False) -> Type;


False = %fix(T, False : Type) : (I : T -> Type) -> (f : I False) -> Type.
  (I : T -> Type) => (f : I False) =>
  (P : I False -> Type) -> P f;

False = False (False => )
%self(T, False). (f : )

((F : Type) => (False : F -> Type) => (f : F) => False f);
%self(F, f). I F False f

%self(FalseT, False). (f : %self(f). False f) -> Type

False = %self(False. f). (P : False -> Type) -> P f;

Constructors

-----------
Self : Type

Γ |- M : Self
----------------
%typeof M : Type

Γ |- M : Self
----------------------
%unpack M : %typeof M

Γ, x : Self |- T : Type
-----------------------
%self(x). T : Type


Γ, x : %self(x). T : T
----------------------
%self(x). T : Type

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]


Γ |- M : %self(A, x). T
-------------------------------------------
%unroll M : T[A := %self(A, x). T | x := M]

%self(False). (I : Self -> Self -> Type) ->
  (f : %self(f). I False f) -> Type;

%self(f). (P : False I -> Type) -> P (I f);

unit = P => (x : P unit) => x

%self(A, x). T

Γ, x : A |- B : Type
----------------------
%self(x : A). B : Type

Γ, x : A |- M : B
--------------------------------
%fix(x : A). M : %self(x : A). B

Γ |- M : %self(x : A). B
------------------------
%unroll M : T[x := M]

%self(False).
%self(x : A). B

Back to Magic Self

%self(Unit).
  (a : %self(b). Unit b b) ->
  (c : %self(d). Unit a d) -> Type;

%self(Unit).
  (a : %self(b). (? : (%self(d). Unit a d) -> Type) b) ->
  (c : %self(d). Unit a d) -> Type;

%self(Unit). (a : %self(b). %unroll Unit b b) -> (c : %self(d). %unroll Unit a d) -> Type;
%self. (%self. %unroll 1 0 0) -> (%self. %unroll 2 1 0) -> Type

%self. %unroll (1 : %self. (%self. %unroll 1 0 0) -> (%self. %unroll 2 1 0) -> Type) 0 0
%self. (%unroll 1 : (%self. %unroll 2 0 0) -> (%self. %unroll 3 1 0) -> Type) 0 0
%self. (%unroll 1 0 : (%self. %unroll 2 0 0) -> Type) 0 0



%self. (%self. ((1 0 : ) 0) -> (%self. 2 1 0) -> Type

received : %self. 1 0 0
expected : %self. 2 1 0

(λ.0) 1 === 1
%self(b). Unit b b
%self(d). Unit b d

%self(b). Unit b b
%self(d). Unit a d

%self(unit). Unit unit unit
%self(u). Unit unit u

%self(unit). (P : ? -> Type) -> P unit -> P unit;
%self(unit). (P : ? -> Type) -> P (%fix(unit). P => (x : P unit) => x) -> P unit;

%self(u). (P : ?) -> P u -> P u
Unit = %fix(Unit).
  (P : Unit -> Type) -> P (%fix(unit). P => (x : P unit) => x)

%self(Unit). (a : %self(b). %unroll Unit b b) -> (c : %self(d). %unroll Unit a d) -> Type;
%self(b). %unroll (Unit : %self(Unit). (e : %self(f). %unroll Unit f f) -> (g : %self(h). %unroll Unit e h) -> Type) b b
%self(b). (%unroll Unit : (e : %self(f). %unroll Unit f f) -> (g : %self(h). %unroll Unit e h) -> Type) b b
%self(b). (%unroll Unit (b : %self(b). %unroll Unit b b) : (g : %self(h). %unroll Unit b h) -> Type) b
received : %self(b). %unroll Unit b b; %unroll Unit i i
expected : %self(h). %unroll Unit b h; %unroll Unit i i // replaced b := i here
%self(b). (%unroll Unit b b : Type)

%self. %unroll (1 : %self. (%self. %unroll 1 0 0) -> (%self. %unroll 2 1 0) -> Type) 0 0
%self. (%unroll 1 : (%self. %unroll 2 0 0) -> (%self. %unroll 3 1 0) -> Type) 0 0
%self. (%unroll 1 (0 : %self. %unroll 2 0 0) : (%self. %unroll 2 0 0) -> Type) 0
%self. (%unroll 1 0 : (%self. %unroll 2 0 0) -> Type) (0 : %self. %unroll 2 0 0)
%self. (%unroll 1 0 0 : Type)


%self(Unit). (a : %self(b). %unroll Unit b b) -> (c : %self(d). %unroll Unit a d) -> Type;


fix%Unit (unit : %self(unit). %unroll Unit unit unit) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P unit -> P u;
fix%unit : %unroll Unit unit unit = P => x => x;

Unit = %self(u). %unroll Unit unit u;
unit : Unit = unit;

Kewerson

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

fix%Unit (unit : %self(unit). %unroll Unit unit unit) (u : %self(u). %unroll Unit unit u)
  = (P : (u : %self(u). %unroll Unit unit u) -> Type) -> P unit -> P u;
fix%unit : %unroll Unit unit unit = P => x => x;

Unit = %self(u). %unroll Unit unit u;
unit : Unit = unit;
ind (u : Unit) = %unroll u;

%fix(Unit)
Unit : %self(Unit).
  (unit : %self(unit). %unroll Unit unit unit) ->
  (u : %self(u). %unroll Unit unit u) -> Type


received : %self(k). %unroll Unit k k // unit := k; u := k
expected : %self(k). %unroll Unit k k // unit := k; u := k

%self. (%self. %unroll 1 0 0) -> (%self. %unroll 2 1 0) -> Type

%self. %unroll (1 : %self. (%self. %unroll 1 0 0) -> (%self. %unroll 2 1 0) -> Type) 0 0
%self. (%unroll 1 : (%self. %unroll 2 0 0) -> (%self. %unroll 3 1 0) -> Type) 0 0
%self. (%unroll 1 (0 : %self. %unroll 2 0 0) : (%self. %unroll 2 0 0) -> Type) 0
%self. (%unroll 1 0 0 : Type)

fix%Unit (self%unit : %unroll Unit unit unit) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P unit -> P u;
fix%unit : %unroll Unit unit unit = P => x => x;

@Unit (@unit : @Unit unit unit) (@u : @Unit unit u) : Type =
  (P : (@u : @Unit unit u) -> Type) -> P unit -> P u;
Unit = u @-> Unit unit u;

Unit = %self(u). %unroll Unit unit u;
unit : Unit = unit;

@>
%self(f). (x) => x
@f. (x) => x
@f(x) => x

λa. λb. b === λc. λd. d
λa. λb. a === λc. λd. c

λλ0 === λλ0 1 2
λλ1 === λλ1

formation : (x : Int) -> Int
introduction : (x : Int) => x
elimination : lambda arg

formation : %self(x). T
introduction : %fix(x) : T. m
elimination : %unroll x

%fix(0 Rec). (n : Rec) -> Int

%self(x, y). (x : Int, y : Int)
Int ->! Int;
(x => x(x)) : %fix(0 Rec). (1 : Rec) -> Int;

%self(False). (f : %self(f). False f) -> Type;

(%fix(x) : T. (m : T)) : %self(x). T
%fix(x : T). m
((x : %fix(Rec). Rec -> Int) => (%unroll x)(x))


%fix(x) : T. x
let rec f x = x + f x

let f = fun self x -> x + self x
let f = %fix(self). f self;

- -> +
%fix(Rec). Rec -> Int

fold : Nat -> (A : Type) -> A -> (A -> A) -> A;
case : Nat -> (A : Type) -> A -> (Nat -> A) -> A;

Nat = (A : Type) -> A -> (Nat -> A) -> A;

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;

Bool = (P : (0 Bool) -> Type) -> P true -> P false -> P b;

b => (P : Bool -> Type) -> P true -> P b;

%fix(Rec). (0 Rec) -> Int

((0 x : %fix(Rec). (0 Rec) -> Int) => 1)


Type : Type
((A : Type) -> A) : Type

(A : Type) => (x : A) => x;

(x => y => y)
(a => b => b)

f ((x : Int) => x)
f ((y : Int) => y)

Unit @-> (unit : unit @-> Unit unit unit) @-> (u @-> Unit unit u) -> Type

received : unit @-> Unit unit unit
expected : u @-> Unit unit u

Array.set : Array<A> -> Int -> A -> Array<A>;
f = (arr : Array<Int>) => (
  arr = Array.set(arr, 0, 0);
  arr = Array.set(arr, 1, 1);
);

Array.set : &mut Array<A> -> Int -> A -> ();
f = (arr : Array<Int>) => (
  Array.set(arr, 0, 0);
  Array.set(arr, 1, 1);
);

f : () -> Int;
f() === f();

incr = x => x + 1;

incr 1 === (x => x + 1) 1;

acc = 0;
f = () => acc;
x = f

double = (x : User) => (
  let () = free(x);
  1
);

(x => x + x)

x.y := x;

Socket : Type;
connect : () -> Socket;
close : Socket -> ();

f = () => (
  socket = connect();
  close(socket);
  1
)


f : %self(False). (f : %self(f). False f (x => x)) -> (k : Int -> Int) Type;

False :
(f : %self(f). False f) -> Type

(f : %self(f). %unroll False f) -> Type

P Int ((x : Int) => x)
P Bool ((x : Bool) => x)

(x : Int) -> Int

Inference and Linearity

Rank-2 allows for existential types. Infinite rank-1 instances.

Maybe some polymorphic recursion thing?

Linear Rank-2

It only allows for one instance, so is it isomorphic to just having monomorphized signatures?

Can you always monomorphize rank-2 polymorphism?

Again

@False (@f : False f) = (P : (@f : False f) -> Type) -> P f;

False @=> (@f : False f) => (P : (@f : False f) -> Type) -> P f;

False @=> (@f : (False @=> (@f : False f) => (P : (@f : False f) -> Type) -> P f) f) => (P : (@f : False f) -> Type) -> P f;

False : False @-> (f : f @-> @False f) -> Type ===
      ((False : False @-> (f : f @-> @False f) -> Type) @=>
        (f : f @-> @False f) => (P : (f : f @-> @False f) -> Type) -> P f);
    False

Even More Self

%self(False). (f : %self(f). False f) -> Type

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

fix%Unit (a : %self(b). %unroll Unit b b) (c : %self(d). %unroll Unit a d) =
  (P : (e : %self(f). %unroll Unit a f) -> Type) -> P a -> P c;

%self(Unit). (a : %self(b). %unroll Unit b b) -> (c : %self(d). %unroll Unit a d) -> Type;

%fix. (%self. %unroll \1 \0 \0) => (%self. %unroll \2 \1 \0) =>
  ((%self. %unroll \3 \2 \0) -> Type) -> \0 \2;

%fix. (%self. %unroll \1 \0 \0) => (%self. %unroll \2 \1 \0) =>
  ((%self. %unroll \3 \2 \0) -> Type) -> \0 \2;

((\0 : (%self. %unroll \4 \3 \0) -> Type) (\2 : %self. %unroll \4 \0 \0))

fix%Unit
  (I : %self(I). (unit : %self(unit). (P : %unroll Unit I unit -> Type) -> P (I unit unit) -> P (I unit unit)) ->
    (u : %self(u). (P : %unroll Unit I unit -> Type) -> P (I unit unit) -> P (I unit u)) -> %unroll Unit I unit)
  (unit : %self(unit). (P : %unroll Unit I unit -> Type) -> P (I unit unit) -> P (I unit unit)) =
  %self(u). (P : %unroll Unit I unit -> Type) -> P (I unit unit) -> P (I unit u);

%self(Unit).
  (I : %self(I). (unit : %self(unit). (P : %unroll Unit I unit -> Type) -> P (I unit unit) -> P (I unit unit)) ->
    (u : %self(u). (P : %unroll Unit I unit -> Type) -> P (I unit unit) -> P (I unit u)) -> %unroll Unit I unit) ->
  (unit : %self(unit). (P : %unroll Unit I unit -> Type) -> P (I unit unit) -> P (I unit unit)) -> Type;

%self(Unit).
  (A : %self(B). (c : %self(d). (P : %unroll Unit B d -> Type) -> P (B d d) -> P (B d d)) ->
    (e : %self(f). (P : %unroll Unit B c -> Type) -> P (B c c) -> P (B c f)) -> %unroll Unit B c) ->
  (g : %self(h). (P : %unroll Unit A h -> Type) -> P (A h h) -> P (A h h)) -> Type;

%self(B). (c : %self(d). (P : %unroll Unit B d -> Type) -> P (B d d) -> P (B d d)) ->
    (e : %self(f). (P : %unroll Unit B c -> Type) -> P (B c c) -> P (B c f)) -> %unroll Unit B c

expected : %self(f). %unroll Unit a f
received : %self(b). %unroll Unit b b


Unit @->
  (I : I @-> (unit : unit @-> (P : (u : @Unit I unit) -> Type) -> (x : P (@I unit unit)) -> P (@I unit unit)) ->
    (u : u @-> (P : (u : @Unit I unit) -> Type) -> (x : P (@I unit unit)) -> P (@I unit u)) -> @Unit I unit) ->
  (unit : unit @-> (P : (u : @Unit I unit) -> Type) -> (x : P (@I unit unit)) -> P (@I unit unit)) -> Type


Unit @->
  (A : B @-> (c : d @-> (P : (u : @Unit B d) -> Type) -> (x : P (@B d d)) -> P (@B d d)) ->
    (e : f @-> (P : (g : @Unit B c) -> Type) -> (x : P (@B c c)) -> P (@B c f)) -> @Unit B c) ->
  (h : i @-> (P : (l : @Unit A i) -> Type) -> (x : P (@A i i)) -> P (@A i i)) -> Type


B @-> (c : d @-> (P : (u : @Unit B d) -> Type) -> (x : P (@B d d)) -> P (@B d d)) ->
    (e : f @-> (P : (g : @Unit B c) -> Type) -> (x : P (@B c c)) -> P (@B c f)) -> @Unit B c

%fix. (%self. %unroll \1 \0 \0) => (%self. %unroll \2 \1 \0) =>
  ((%self. %unroll \3 \2 \0) -> Type) -> \0 \2;

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u) =
  (P : (u : %self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%Unit I (unit : %self(unit). %unroll Unit unit u) =
  %self(u). (P : (u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P (I u);

Unit @->
  (I : I @-> (unit : unit @-> @Unit I unit) ->
    (u : u @-> (P : (u : @Unit I unit) -> Type) -> (x : P @unit) -> P (@I unit u)) -> @Unit I unit) ->
  (unit : unit @-> @Unit I unit) -> Type

Unit @->
  (I : I @-> (unit : unit @-> @Unit I unit) ->
    (u : u @-> (P : (u : @Unit I unit) -> Type) -> (x : P @unit) -> P (@I unit u)) -> @Unit I unit) ->
  (unit : unit @-> @Unit I unit) -> Type


fix%Unit I (unit : %self(unit). %unroll Unit unit u) =
  %self(u). (P : (u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P (I u);

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u) =
  (P : (u : %self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%unit : %self(u). %unroll Unit unit u.

fix%Unit (a : %self(b). %unroll Unit b b) (c : %self(d). %unroll Unit a d) =
  (P : (e : %self(f). %unroll Unit a f) -> Type) -> P a -> P c;

Unit : Type
unit : Unit

Unit = %self(u)

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u) =
  (P : (u : %self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%False (f : %self(f). False f) =
fix%Unit (unit : %self(unit). Unit unit) =
  %self(u). (P : (u : Unit unit) -> Type) -> P unit -> P u;
fix%Unit =
  %self(u). (P : Unit -> Type) -> P (%fix(unit : Unit). P => x => x) -> P u;

%self(u). (P : Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u) =
  (P : (u : %self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;
Unit1 = (unit : %self(unit). %self(u). %unroll Unit unit u) => %self(u). Unit unit u;
fix%Unit (a : %self(b). %unroll Unit b b) (c : %self(d). %unroll Unit a d) =
  (P : (e : %self(f). %unroll Unit a f) -> Type) -> P a -> P c;

fix%Unit = %self(u). (P : Unit -> Type) -> P (%fix(unit). P => x => x) -> P u;




unit : %self(unit). (P : Unit -> Type) -> P unit -> P unit;
%coerce unit : %self(u). (P : Unit -> Type) -> P unit -> P u;

%fold unit : %self(u). (P : Unit -> Type) -> P unit -> P u;
() -> (P : Unit -> Type) -> P unit -> P u;

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u) =
  (P : (u : %self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

%fix(unit). %fix(u) : (I : ?) -> Unit (unit I) u.
  P => (x : P (%unroll unit)) => (x : P u)

%fix(unit). %fix(u) : Unit unit u. P =>
  (x : P (%fix(u) : Unit unit u. P => (x : P (%unroll unit)) => (x : P u))) =>
  (x : P (%fix(u) : Unit unit u. P => (x : P (%unroll unit)) => (x : P u)))

%self(unit). %fix(). Unit (I unit) (I u)
%fix(unit) : %fix(u). Unit () u.
  P => (x : P (%unroll unit)) => (x : P u)

M : %self(unit). %self(u). %unroll Unit unit u
%unroll M : %self(u). %unroll Unit unit u



fix%Unit (I : %self(I). ((A : Type) -> A -> A) -> Unit I) =
  %self(u). (P : Unit I -> Type) ->
    P (I (A => x => x)) -> P (I (A => %unroll u (_ => A)));

Unit1 = Unit (%fix(I). unit =>
  %fix(u). (P : Unit I -> Type) => (
)
%self(u). (P : Unit I1 I2 -> Type) ->
    P (I2 (%fix(unit). P => x => x)) -> P (I1 I2 u);

Unit1 = Unit (%fix(I1). I2 => x => x);
%fix(I1). unit =>

fix%unit (I : unit ==) : %self(u). %unroll Unit I unit u =

  %unroll (%fix(u). (I : %unroll unit == u) -> Unit I unit u. P => x => I P x)
    ;

Why?

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, x : A |- M : B
--------------------------------
%fix(x : A). M : %self(x : A). B

Γ |- M : %self(x). T
-----------------------------
%unroll M : T[x := %unroll M]

x == y /\ x <> y

Unit0 Unit unit u =
  (P : Unit -> Type) -> P unit -> P u;

%self(Unit, _). (I : ?) -> Type

%self(F, f). (P : F -> Type) -> P f;
Unit0 U1 unit U2 u =
  (P : (A : Type) -> A -> Type) -> P U1 unit -> P U2 u;
unit = %fix(U1, unit) : Unit0 U1 unit U1 unit = P => x => x;

Unit1 = %self(U, u). Unit0 _ unit U u;

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ |- M[x := %fix(x). M] : T
----------------------------
%fix(x) : T. M : %self(x). T

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]

%self(False). (f : %self())

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u) =
  (P : (u : %self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%unit I1 = (
  u = %fix(u) : (I2 : %unroll (unit I1) == (u I2)) -> Unit (unit I1) (u I2).
    I2 => P => x => I P x;


)

%unroll (%fix(u) : (I : %unroll unit = %unroll u I) -> Unit unit (%unroll u I).
  I => P => (x : P (%unroll unit)) => I P x)

(I : %unroll unit = %unroll (%fix(u) : (I : %unroll unit = %unroll u I) -> Unit unit (%unroll u I).
  I => P => (x : P (%unroll unit)) => I P x) I) => P => (x : P (%unroll unit)) => I P x

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u) =
  (P : (u : %self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

Unit =
  %fix(Unit0). (unit : %self(unit). %unroll Unit0 unit (%fix(I). u => u)) =>
  %fix(Unit1). (I : (u : %self(u). (P : (u : %unroll Unit1 I) -> Type) -> P unit -> P u) -> %unroll Unit1 I) =>
    %self(u). (P : (u : %unroll Unit1 I) -> Type) -> P unit -> P u;


%self(False). (f : %self(f). False f) -> Type

%self(Unit). (u : (unit : ?) -> %self(u). Unit u) -> Type

fix%Unit
  (I : %self(I).
    (unit : %self(unit). Unit I unit) ->
    (u : %self(u). (P : Unit I unit -> Type) -> P unit -> P (I unit u)) ->
    %self(u). Unit I u
  )
  (unit : %self(unit). Unit I unit) =
  %self(u). (P : Unit I unit -> Type) -> P unit -> P (I unit u);


fix%Unit
  (A : %self(B).
    (c : %self(d). Unit B d) ->
    (e : %self(f). (P : Unit B c -> Type) -> P (%unroll c) -> P (B c f)) ->
    %self(g). Unit B g
  )
  (h : %self(i). Unit A i) =
  %self(j). (P : Unit A h -> Type) -> P (%unroll h) -> P (A h j);

Unit : Type
unit : Unit

Unit = %self(u). (P : Unit -> Type)

Unit0 W = %fix(Unit). (P : Unit -> Type) -> W Unit;
Unit1 = Unit0 (Unit => )

fix%Unit
  (I : %self(I).
    (unit : %self(unit). Unit I unit) ->
    (u : %self(u). (P : Unit I unit -> Type) -> P unit -> P (I unit u)) ->
    %self(u). Unit I u
  )
  (unit : %self(unit). Unit I unit) =
  %self(u). (P : Unit I unit -> Type) -> P unit -> P (I (%unroll u));

fix%Unit (unit : %self(unit). Unit unit) =
  %self(u). (P : Unit unit -> Type) -> P (%unroll unit) -> P u;
fix%unit : Unit unit =
  %fix(u). P => x => x;

Unit = Unit (%fix(unit). %fix(u). P => x => x);


fix%Unit =
  %self(u). (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P u;

fix%Unit =
  %self(u). (P : Unit unit -> Type) -> P (%unroll unit) -> P u;

inductionBool : forall (P : ((A : Type) -> A -> A -> A) -> Type), P false -> P true -> forall (b : (A : Type) -> A -> A -> A), P b



%fix(Unit). %self(b). (P : Unit -> Type) ->
  P (%fix(unit). P => x => x) -> P b

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, x == %fix(x). M |- M : T
----------------------------
%fix(x) : T. M : %self(x). T

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]

type ty_term = TT_typed of { term : term; type_ : term }
and term =
  | TT_var of { var : Var.t }
  | TT_forall of { param : ty_pat; return : term }
  | TT_lambda of { param : ty_pat; return : term }
  | TT_apply of { lambda : term; arg : term }
  | TT_self of { bound : pat; body : term }
  | TT_fix of { bound : ty_pat; body : term }
  | TT_unroll of { term : term }

and ty_pat = TP_typed of { pat : pat; type_ : term }
and pat = TP_var of { var : Var.t }

ChatGPT

Compression

Makes GPT compress previous sessions, so that sessions can be merged.

ChatGPT protocol

I like succint and direct conversations, avoid apologizing.

Working on the core calculus for a dependently typed programming language.

Common pattern for types


Session Header:

  • Date: 2023-03-14
  • Session ID: 5d53713f-87d4-4fa8-8480-655bb0e5467d
  • User: EduardoRFS
  • Language: English
  • Topic: Implementing Smol in OCaml
  • Special Instructions: Be succint and direct, avoid apologizing

Session Context:

Smol is the core for a dependently typed programming language, based on the Calculus of Construction and extendended with self types similar to how Aaron Stump and Peng Fu describe at Self Types for Dependently Typed Lambda Encodings.

The main changes from the Calculus of Construction are the following rules

-----------
Type : Type

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, x == %fix(x). M |- M : T
----------------------------
%fix(x) : T. M : %self(x). T

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]

The context was extended with definition equalities such that inside of the fixpoint, x is known to be equal to the fixpoint.

On the implementation, the current tree is defined as

type ty_term = TT_typed of { term : term; type_ : term }

and term =
  | TT_var of { var : Var.t }
  | TT_forall of { param : ty_pat; return : term }
  | TT_lambda of { param : ty_pat; return : term }
  | TT_apply of { lambda : term; arg : term }
  | TT_self of { bound : pat; body : term }
  | TT_fix of { bound : ty_pat; body : term }
  | TT_unroll of { term : term }

and ty_pat = TP_typed of { pat : pat; type_ : term }
and pat = TP_var of { var : Var.t }
module Context : sig
  type t
  type term

  val empty : t
  val extend_abstract : t -> Var.t -> term -> t
  val extend_alias : t -> Var.t -> term -> t
  val lookup : t -> Var.t -> term option
end

Assume

module Ttree : sig
  type ty_term = TT_typed of { term : term; type_ : term }

  and term =
    | TT_var of { var : Var.t }
    | TT_forall of { param : ty_pat; return : term }
    | TT_lambda of { param : ty_pat; return : term }
    | TT_apply of { lambda : term; arg : term }
    | TT_self of { bound : pat; body : term }
    | TT_fix of { bound : ty_pat; body : term }
    | TT_unroll of { term : term }

  and ty_pat = TP_typed of { pat : pat; type_ : term }
  and pat = TP_var of { var : Var.t }
end
module Subst : sig
  val subst_term : from:Var.t -> to_:Var.t -> Ttree.term -> Ttree.term
end
module Context : sig
  type context
  type t = context

  val initial : context
  val enter : Var.t -> Ttree.term -> context -> context
  val lookup : Var.t -> context -> Ttree.term option
end

Then implement

module Equal : sig
  val equal_term : Context.t -> received:Ttree.term -> expected:Ttree.term -> unit
end

Internal Fix Again

%fix(False) : Type. %self(f). (P : %unroll False -> Type) -> P f


%fix(False) : Type. %self(f). (P : %unroll False -> Type) -> P f
%unroll (%fix(False\1) : Type. %self(f). (P : %unroll False -> Type) -> P f)

%self(f). (P : %unroll False -> Type) -> P f

%unroll (%fix(False\1) : Type. %self(f). (P : %unroll False -> Type) -> P f)

expected : %self(f). (P : %unroll False\0 -> Type) -> P f
received : f\1

expected : %self(f : %unroll False). (P : %unroll False -> Type) -> P f
received : %self(f : %unroll False). (P : %unroll False -> Type) -> P f


%fix(False\1) : Type. %self(f). (P : %unroll False -> Type) -> P f

expected : %unroll (%fix(False\1) : Type. %self(f). (P : %unroll False -> Type) -> P f)
received : %self(f). (P : %unroll False -> Type) -> P f

expected : %unroll (%fix(False) : Type. %self(f) : %unroll False/2. (P : %unroll False/1 -> Type) -> P f)
received : %self(f) : %unroll False/2. (P : %unroll False/1 -> Type) -> P f

expected : %self(f) : %unroll False/2. (P : %unroll False/1 -> Type) -> P f
received : %self(f) : %unroll False/2. (P : %unroll False/1 -> Type) -> P f

fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u) =
  (P : (u : %self(f). Unit unit u) -> Type) -> P unit -> P u;

%fix(unit) : %self(u). Unit unit u.
  %fix(u) : Unit unit !u. (P : (u : %self(f). Unit unit u) -> Type) => (x : P (%unroll !unit)) => x

expected : P (%fix(u) : Unit unit !u. (P : (u : %self(f). Unit unit u) -> Type) => (x : P (%unroll !unit)) => x)
received : P (%fix(u) : Unit unit !u. (P : (u : %self(f). Unit unit u) -> Type) => (x : P (%unroll !unit)) => x)

expected : P u\0
received : P (%fix(u\0) : Unit unit u. (P : (u : %self(f). Unit unit u) -> Type) => (x : P (%unroll unit)) => x)

expected : %unroll False
received : %self(f). (P : %unroll False -> Type) -> P f

expected : %unroll False2
received : %self(f). (P : %unroll False1 -> Type) -> P f

expected : %unroll (%fix(False1). %self(f). (P : %unroll False1 -> Type) -> P f)
received : %self(f). (P : %unroll False1 -> Type) -> P f


expected : %self(f). (P : %unroll False1 -> Type) -> P f
received : %self(f). (P : %unroll False1 -> Type) -> P f

expected : %self(f). (P : %unroll (%frozen(False3). %self(f). (P : %unroll False3 -> Type) -> P f) -> Type) -> P f
received : %self(f). (P : %unroll (%frozen(False2). %self(f). (P : %unroll False2 -> Type) -> P f) -> Type) -> P f

P : %unroll (%expanded(False). %self(f). (P : %unroll False -> Type) -> P f) -> Type

expected : %unroll (%expanded(False). %self(f). (P : %unroll False -> Type) -> P f)
received : %self(f). (P : %unroll False -> Type) -> P f

expected : %self(f). (P : %unroll False -> Type) -> P f
received : %self(f). (P : %unroll False -> Type) -> P f

expected : %self(f). (P : %unroll (%expand (%frozen False)) -> Type) -> P f
received : %self(f). (P : %unroll (%expand False) -> Type) -> P f

expected : %unroll (%expanded(False). %self(f). (P : %unroll False -> Type) -> P f)
received : %self(f). (P : %unroll (%expanded(False). %self(f). (P : %unroll False -> Type) -> P f) -> Type) -> P f

expected : %self(f). (P : %unroll (%frozen(False). %self(f). (P : %unroll False -> Type) -> P f) -> Type) -> P f
received : %self(f). (P : %unroll (%expanded(False). %self(f). (P : %unroll False -> Type) -> P f) -> Type) -> P f

expected : %unroll (%frozen(False). %self(f). (P : %unroll () -> Type) -> P f)
received : %self(f). (P : %unroll (%frozen(False). %self(f). (P : %unroll () -> Type) -> P f) -> Type) -> P f

expected : %unroll False
received : %self(f). (P : %unroll False -> Type) -> P f

expected : %unroll (%fix(False). %self(f). (P : %unroll False -> Type) -> P f)
received : %self(f). (P : %unroll (%fix(False). %self(f). (P : %unroll False -> Type) -> P f) -> Type) -> P f

expected : %unroll (%fix(False). %self(f). (P : %unroll False -> Type) -> P f)
received : %self(f). (P : %unroll False -> Type) -> P f

expected : %self(f). (P : %unroll False -> Type) -> P f
received : %self(f). (P : %unroll False -> Type) -> P f

%fix(Unit). %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

expected : %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u
received : %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

%fix(Unit). %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

%fix(unit) : %unroll Unit. P => x => x

expected : P (%fix(unit). P => x => x)
received : P (%fix(unit). P => x => x)


%frozen(Unit). %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

expected : %unroll Unit
received : %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

expected : %unroll (%fix(Unit). %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u)
received : %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

expected : %self(u). (P : %unroll (%frozen(Unit). %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u) -> Type) -> P (%fix(unit). P => x => x) -> P u
received : %self(u). (P : %unroll Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

T = %self(u). (P : Unit unit -> Type) -> P (%unroll unit) -> P u;
fix%unit

Unit0 (unit : %self(unit). Unit unit) =
  (P : (u : %self(u). Unit0 u) -> Type) -> P unit -> P unit;
fix%unit : Unit0 unit = P => x => x;


%self(unit). %self(u). Unit unit u
%self(u). Unit unit u

fix%Unit (unit : %self(unit). %self(u). Unit unit u) u =
  (P : (u : %self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%unit : %self(u). Unit unit u =


fix%Unit =
  %self(u).
    (P : (u : %self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u

(P : Unit -> Type) -> P unit -> P u;

Ord = (Base : Type) -> (Wrap : Type -> Type) -> Type;
Zero : Ord = Base => Wrap => Base;
Succ (N : Ord) : Ord = Base => Wrap => Wrap (N Ord Base);

False0 = (A : Type) -> A;
FalseN (N : Ord) : Ord =
  N ((False : Type) -> (f : False) -> Type) False0
    (False => (f : False) => (P : False -> Type) -> P f);

False0 : (f0 : False) -> Type = f0 => (P : False -> Type) -> P f0;
False1 : (f0 : False) -> (f1 : False0 f0) -> Type = f0 => f1 => (P : False0 f0 -> Type) -> P f1;
False2 : (f0 : False) -> (f1 : False0 f0) -> (f2 : False1 f0 f1) -> Type
  = f0 => f1 => f2 => (P : False1 f0 f1 -> Type) -> P f2;

FalseT (N : Ord) = N Falsep

f0 => f1 => f (P : ((P : False0 -> Type) -> P f0) -> Type) -> P f1;
f (f (f False0))
f (f (f n))

x = (f : False 2 )
// TODO: generic base case for all types
Unit0 = (A : Type) -> (x : A) -> A;
unit0 : Unit0 = A => x => x;


Unit (N : Ord) = N Unit0 (Unit => => (P : ))



(A : Type) => (x : A) => x;

False False (f : False) = (P : False -> Type) -> P f;


(f : Self False)

%fix(False) : Type. %self(f : %unroll False).
  (P : %unroll False -> Type) -> P f;


%self(A, False : (f : A) -> Type).
  (f : %self(T, f : A). False f) -> Type;
%fix(Unit) : Type. %self(u : %unroll Unit).
  (P : %unroll Unit -> Type) ->
  P (%fix(unit). (P : %unroll Unit -> Type) => (x : P unit) => x) -> P u

%fix(Unit). %self(u). (P : Unit -> Type) -> P (%fix(unit). P => x => x) -> P u

Unit : Type;
unit : Unit;

Unit = %self(u). (P : Unit -> Type) -> P unit -> P u;

ind_unit : (u : Unit) -> (P : Unit -> Type) -> P unit -> P u;


(x : A) -> B : Type
%unroll u : (P : Unit -> Type) -> P unit -> P u


fix%Unit = (
  unit = %fix(unit : %unroll Unit). (P : %unroll Unit -> Type) => (x : P unit) => x;
  %self(u : %unroll Unit). (P : %unroll Unit -> Type) -> P unit -> P u
);

[%fix(unit). (P : Unit -> Type) => (x : P unit) => x : Unit,
 %self(u : Unit). (P : Unit -> Type) -> P unit -> P u === Unit]

%self(False : T). (f : %self(f). %unroll False f) -> Type

%fix(FalseT) : Type. %self(False : FalseT).
  (f : %fix(fT) : Type. %self(f : fT). (False : (f : fT) -> Type) f) -> Type

%fix(TFalse) : Type. %self(False : %unroll TFalse).
  (f : %fix(Tf) : Type.
    %self(f : %unroll Tf). %unroll (False : %self(False). (f : %unroll Tf) -> Type) f) -> Type

%fix(TFalse) : Type. %self(False : %unroll TFalse).
  (f : %fix(Tf) : Type.
    %self(f : %unroll Tf). %unroll (False : %self(False). (f : %unroll Tf) -> Type) f) -> Type

%fix(TFalse) : Type. %self(False : %unroll TFalse).
  (f : %fix(Tf) : Type, False : %self(False). (f : %unroll Tf) -> Type.
    %self(f : %unroll Tf). %unroll False f) -> Type

%self(False). (f : %self(f : %unroll Tf). %unroll False f) -> Type

%self(f : %unroll Tf). %unroll (False : %self(False). (f : %unroll Tf) -> Type) f === %unroll Tf


False : FalseT
FalseT === (f : fT) -> Type

%fix(unit). (P : Unit -> Type) => (x : P unit) => x
%self(u : Unit). (P : Unit -> Type) -> P unit -> P u


%fix(FalseT) : Type. %self(False : FalseT).
  (f : %fix(fT) : Type. %self(f : fT). (False : (f : fT) -> Type) f) -> Type

%fix(TFalse) : Type. %self(False : %unroll TFalse).
  (f : %fix(Tf) : Type, False : %self(False). (f : %unroll Tf) -> Type.
    %self(f : %unroll Tf). %unroll False f) -> Type

%fix(False).
  %self(f). (P : %unroll False -> Type) -> P f

fix%Unit (unit : %self(unit). %self(u). Unit unit u) u =
  (P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;
fix%unit : %self(u). Unit unit u = P => x => (x : P u)
fix%Unit = (
  unit : %unroll (Unit 1) = %fix(u). P => x => x;
  %self(u). (P : %unroll (Unit 0) -> Type) -> P unit -> P (u : Unit 1)
);

%fix(Unit). (P : Unit -> Thype)

Symbol Pushing

double = (x) => x + x;

double(2);
((x) => x + x)(2)
(x + x)[x := 2]
2 + 2
4

double(potato);
((x) => x + x)(potato);
(x + x)[x := potato]
potato + potato

double(2);
((x) => x + x)(2)
(x + x)[x := 2]
x[x := 2] + x[x := 2]
2 + 2
4

double(potato) === potato + potato

name(user) = user.name;


name({ name : "Eduardo" });

{ name : "Eduardo" }.name
"Eduardo"



double = (x) => x + x;

name = (user) => user.firstName + " " + user.lastName;


r0 : Register;
r1 : Register;
r2 : Register;
r3 : Register;

one = imm(r0, 1);
two = imm(r1, 1);
(three, one) = add(two, one);
(three, three) = mov(three, one);

ChatGPT Teika

Teika is a dependently typed programming language with inductive types, the main syntax can be seen as described by the following rules:

  • Type is the type of all types, the Type of Type is Type
  • (x : A) => m is a function that accepts x of type A and return M of type B
  • (x : A) -> B is a function type that accepts x of type A returns a type B
  • x = m; n is a let that expresses that in n x will be equal to m

Induction of the booleans is defined in the context as following

Bool : Type;
true : Bool;
false : Bool;
ind_bool : (b : Bool) -> (P : Bool -> Type) -> (t : P true) -> (f : P false) -> P b;

Counter Expansion

%fix(False). %self(f). (P : %unroll (%unfold False) -> Type) -> P f;

%fix(Unit). (
  unit : %unroll Unit = %fix(u). P => (x : P (%unfold u)) => (%fold x);
  %self(u). (P : %unroll (%unfold Unit)) -> P unit -> P u;
);

P (%fix(u). P => (x : P (%unfold u)) => (x : P u))
P u

%fix(Unit). (
  unit : %unroll Unit = %fix(u). P => (x : P u) => x;
  %self(u). (P : %unroll Unit -> Type) -> P unit -> P u;
);

expected : %unroll Unit



%fix(Unit). (
  unit : %unroll Unit = %fix(u). (P : %unroll Unit -> Type) => (x : P u) => x;
  %self(u). (P : %unroll Unit -> Type) -> P unit -> P u;
);

(P : %unroll Unit -> Type) -> P (%fix(u : %unroll Unit). (P : %unroll Unit -> Type) => (x : P u) => x) -> P (%fix(u : %unroll Unit). (P : %unroll Unit -> Type) => (x : P u) => x)
(P : %unroll Unit -> Type) -> P (%fix(u : %unroll Unit). (P : %unroll Unit -> Type) => (x : P u) => x) -> P (%fix(u : %unroll Unit). (P : %unroll Unit -> Type) => (x : P u) => x)

False = %fix(False). (f : %self(f). %unroll False f) =>
  (P : (%self(f). %unroll False f -> Type)) -> P f;
False = %self(f). (P : (%self(f). %unroll False f -> Type)) -> P f;

fix%Unit (unit : %self(unit). %self(u). Unit unit u) u =
  (P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;
fix%unit : %self(u). : Unit unit u =
  %fix(u). P => (x : P (%unroll unit)) => (x : P u);


%fix(u). P => (x : P (%unroll unit)) => x

%fix(u). P => (x : P (%unroll unit)) => (x : P (%fix(u). P => (x : P (%unroll unit)) => x))

expected : P (%fix(u). P => (x : P (%unroll unit)) => x)
received : P u

%unroll (%fix(T) : Type. T)

%unroll (%fix(T) : Type. %unroll T)
%unroll (%frozen(T) : Type. %unroll T)
%fix(Unit).
%fix(Bool). (
  macro%true false = %fix(true : %unroll Bool). P => (t : P true) => (f : P false) => t;
  macro%false true = %fix(false : %unroll Bool). P => (t : P true) => (f : P false) => f;
  true = macro%true (macro%false true);
  false = macro%false (macro%true false);
  %self(b). (P : %unroll Bool -> Type) -> P true -> P false -> P b;
);

fix%Bool
  (true : %self(true). (false : %self(false). %self(b). Bool (%unroll true false) false b) -> %self(b). Bool (%unroll true false) false b)
  (false : %self(false). %self(b). Bool (%unroll true false) false b) (b : %self(b). Bool (%unroll true false) false b) =
  (P : (%self(b). Bool (%unroll true false) false b) -> Type) -> P (%unroll true false) -> P (%unroll false) -> P b;
fix%true (false : %self(false). %self(b). Bool (%unroll true false) false b) : %self(b). Bool (%unroll true false) false b
  = %fix(b). P => t => f => (t : P b);
fix%false : %self(b). Bool (%unroll true false) false b
  = %fix(b). P => t => f => (t : P b);
%fix(Bool). (
  true : %unroll Bool = %fix(true). P => (t : P true) => (f : P (%fix(false). P => (t : P true) => (f : P false) => f)) => t;
  false : %unroll Bool = %fix(false). P => (t : P (%fix(true). P => (t : P true) => (f : P false) => t)) => (f : P false) => f;
  %self(b). (P : %unroll Bool -> Type) -> P true -> P false -> P b;
);

expected : %self(b). (P : %unroll Bool -> Type) -> P true -> P false -> P b
received : %self(true). (P : %unroll Bool -> Type) => (t : P true) => (f : P (%fix(false). P => (t : P true) => (f : P false) => f)) => t


P (%unroll unit)
P (%unroll (%unfold unit))

P u
Unit = %self(u). Unit unit u;

unit (_ => Unit) unit == unit
(u : Unit) => u (u => u (_ => Unit) unit == unit);

(P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u
(P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u


(P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u
(P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u

expected : P (%fix(u). P => (x : P (%unroll unit)) => (x : P u))
received : P (%fix(u). P => (x : P (%unroll unit)) => (x : P u))

expected : %fix(u). P => (x : P (%unroll unit)) => (x : P u)
received : %fix(u). P => (x : P (%unroll unit)) => (x : P u)
(P => (x : P (%unroll (%unfold unit))) => x))

f = (u Ç )
expected : P (%fix(u). P => (x : P (%unfold u)) => x)
received : P (%fix(u). P => (x : P (%unfold u)) => x)

expected : %self(f). (P : %unroll False -> Type) -> P (f : %unroll False)
received : %self(f). (P : %unroll False -> Type) -> P (f : %unroll False)

expected : %unroll (%unfold False)
received : %unroll False
Γ, False == %fix(False). _A, f : %self(f). _B

(P : %unroll False -> Type) -> P f;

expected : _A[False := %fix(False). _A]
received : %self(f). _B


False = %fix(False 1).
  %self(f). (P : %unroll (False 0) -> Type) -> P (f : %unroll (False 1));

%self(f). (P : %unroll (False 0) -> Type) -> P (f : %unroll (False 0))
%self(f). (P : %unroll (False 0) -> Type) -> P (f : %unroll (False 1))

Unit = %fix(Unit 1). (
  unit : %unroll (Unit 1) = %fix(u). P => x => x;
  %self(u). (P : %unroll (Unit 0) -> Type) -> P unit -> P (u : Unit 1)
);

%unroll (%fix(Unit 0). (
  unit : %unroll (Unit 1) = %fix(u). P => x => x;
  %self(u). (P : %unroll (Unit 0) -> Type) -> P unit -> P (u : Unit 1)
))

Functional is just algebra

1 + 2 = 3

2 - y = y
y + 2 - y = y + y
2 = 2y
2 / 2 = 2y / 2
1 = y

1 + 2 // 3

f = x => 1 + x;

f(2)
(x => 1 + x)(2)
(1 + x)[x := 2]
1 + 2

f(3)
(x => 1 + x)(3)
(1 + x)[x := 3]
1 + 3

0 + n = n
n + 1 = n

0
S(n) = n + 1

S(0) = 1
S(S(0)) = 2

zero = z => s => z;
succ = n => z => s => s(n(z)(s));

one = succ(zero);
two = succ(one);

add = n => m => n(m)(succ);

succ(succ(two));

one = z => s => s(z);
two = z => s => s(s(z));
three = z => s => s(s(s(z)));

P(n)
0
S(n)

Linear Types Changed The World

Array.get : Array<A> -> Nat -> A;
arr => (Array.get(arr, 0), Array.get(arr, 1));

Array.get : Array<A> -> Nat -> (Array<A>, A);
arr => (
  (arr, x) = Array.get(arr, 0);
  (arr, y) = Array.get(arr, 1);
  (x, y)
);

x => x

x => x + x

Back to no internal expansion

Unit : Type;
unit : Unit;
ind : (u : Unit) -> (P : Unit -> Type) -> P unit -> P u;
// internalizing induction


((n : Nat) -> P n -> P (succ n))

Nat = (A : Type) -> A -> (Nat -> A) -> A

Unit = (P : Unit -> Type) -> P unit -> P u;

%fix(Unit). %self(u). (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P u;

// no self assumption for self

Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

Γ, A : Type, x : A |- M : T
------------------------------
%fix(A, x). M : %self(A, x). T

Γ |- M : %self(A, x). T
-------------------------------------------
%unroll M : T[A := %self(A, x). T | x := M]

%self(False, f). (P : False -> Type) -> P f;

%fix(Unit, unit). (P : Unit -> Type) => (x : P unit) => x;

%self(Unit, unit). (P : Unit -> Type) -> P unit -> P unit

%self(Unit, u). (P : Unit -> Type) -> P unit -> P u;

Unit = %self(Unit, u).  (P : Unit -> Type) -> P unit -> P u;

%self(U, unit). Unit unit;
%fix(U, u : ) :

(A : Type) => (x : A) =>
  (eq : (P : (A : Type) -> A -> Type) -> P Type A -> P Type Nat) =>
  eq (A => x => )

Back to internal expansion

%fix(Unit). %self(u : %unroll (%unfold Unit)). (
  unit = %fix(u : %unroll (%unfold Unit)). (P : %unroll (%unfold Unit) -> Type) => (x : P (%unfold u)) => x;
  (P : %unroll (%unfold Unit) -> Type) -> P unit -> P (%unfold u)
);

fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u) =
  (P : (u : %self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;
unit = %fix(unit). %fix(u) : Unit unit u.
  (P : (u : %self(u). Unit unit u) -> Type) => (x : P (%unroll unit)) => (x : P u);
Unit = %self(u). Unit unit u;

fix%Unit = %self(u). (P : Unit -> Type) -> P (%fix(u : Unit). (P : Unit -> Type) -> P u -> P u) -> P u

expected : (P : Unit -> Type) -> P (%fix(u : Unit). (P : Unit -> Type) -> P u -> P u) -> P (%fix(u : Unit). (P : Unit -> Type) -> P u -> P u)
received : (P : Unit -> Type) -> P (%fix(u : Unit). (P : Unit -> Type) -> P u -> P u) -> P (%fix(u : Unit). (P : Unit -> Type) -> P u -> P u);

expected : P (%fix(u) : Unit unit u. (P : (u : %self(u). Unit unit u) -> Type) => (x : P (%unroll unit)) => (x : P u))
received : P (%fix(u) : Unit unit u. (P : (u : %self(u). Unit unit u) -> Type) => (x : P (%unroll unit)) => (x : P u))

pred => case (%unfold pred)
(P : %unroll (%unfold Unit) -> Type) -> P unit -> P (%unfold u)
(P : %unroll (%unfold Unit) -> Type) -> P (%unfold u) -> P (%unfold u)

fix%False = %self(f). (P : %unfold False -> Type) -> P f;

expected : %unfold False;
received : %self(f). (P : %unfold False -> Type) -> P f;

fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u) =
  (P : Unit -> Type) -> P (%unroll unit) -> P u;
fix%unit : %self(u). Unit (%unfold unit) u = %fix(u) : Unit (%unfold unit) u.
  (P : Unit -> Type) => (x : P (%unroll (%unfold unit))) => x;

fix%unit : %self(u). Unit (%unfold unit) u =
  %fix(u) : Unit (%unfold unit) u. P => x => x;

(P : Unit -> Type) -> P (%unroll (%unfold unit)) -> P (%unroll (%unfold unit));
(P : Unit -> Type) -> P (%unroll (%unfold unit)) -> P

fix%Unit = %self(u). (P : %unfold Unit -> Type) ->
  P (%fix(unit). P => x => x) -> P u;

fix%Unit = %self(u). (P : %unfold Unit -> Type) ->
  P (%fix(unit). P => (x : P unit) => x) -> P u;

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, x == %fix(x). M |- M : T
---------------------------
%fix(x). M : %self(x). T

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]

fix%Unit = %self(u). (P : %unfold Unit -> Type) ->
  P u -> P (%fix(u). P => (x : P u) => (x : P (%fix(u). P => (x : P u) => x)));

symm eq = eq (x => x);

fix%Unit = %self(u). (P : Unit -> Type) ->
  P (%fix(u). P => (x : P u) => x)
u == unit
expected : P (%fix(u). P => (x : P u) => x)
received : P (%fix(u). P => (x : P u) => x)
(P : %unfold Unit -> Type) -> P unit -> P u
(P : %unfold Unit -> Type) -> P (%fix(unit). P => (x : P unit) => x) -> P u

%fix(unit). (P : %unfold Unit -> Type) => (x : P unit) => (x : P unit)

%fix(unit). (P : %unfold Unit -> Type) => (x : P unit) => (x : P unit)

%self(unit). (P : %unfold Unit -> Type) -> P unit -> P unit


M : %self(x). T

received : P unit
expected :

received : P (%fix(unit). P => x => x)
expected : P (%fix(unit). P => x => x)

fix%Unit =
  %self(u). (P : !Unit -> Type) -> P u^ -> P (%fix(u). P => (x : P u^) => !x);

expected : (P : Unit -> Type) -> P u^ -> P (%fix(u). P => (x : P u^) => !x)
received : (P : Unit -> Type) -> P u^ -> P (%fix(u). P => (x : P u^) => !x)

fix%Unit =
  %self(u). (P : !Unit -> Type) -> P (%fix(u). P => (x : P u) => [x]) -> P u^;

expected : (P : !Unit -> Type) -> P (%fix(u). P => (x : P u) => [x]) -> P u^
received : (P : !Unit -> Type) -> P u -> P u


fix%Unit = %self(u).
  (P : Unit -> Type) -> P [u] -> P (%fix(u). P => (x : P [u]) => x);

expected : (P : (!Unit)^ -> Type) -> P [u] ->
received : (P : (!Unit)^ -> Type) -> P [u] -> P [u]

fix%Unit = %self(u).
  (P : %unroll Unit -> Type) -> P (%fix(u). P => (x : P u) => x) -> P u;

(u : Unit) => %unroll u ()
%unroll Unit
(P : %unroll Unit -> Type) -> P (%fix(u). P => (x : P u) => x) -> P u

%unroll Unit
P (%fix(u). P => (x : P u) => x) -> P (%fix(u). P => (x : P u) => x)
P (%fix(u). P => (x : P u) => x) -> P (%fix(u). P => (x : P u) => x)

fix%False = %self(f). (P : %unroll (%unfold False) -> Type) -> P f;

%unroll (%fix(False). %self(f). (P : %unroll (%unfold False) -> Type) -> P f)

fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u)
  = (P : (u : %self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;
fix%unit : %self(u). Unit unit u = %fix(u) : Unit unit u.
  P => (x : P u) => x;

expected : P u -> P u
received : P (%unroll (%unfold unit)) -> P u

%fix(T) : Type. %unroll !T

%fix(Nat). (A : Type) -> A -> (%unroll Nat -> A) -> A;

%fix(Nat). (A : Type) -> A -> (%unroll (%fix(Nat). (A : Type) -> A -> (Nat -> A) -> A) -> A) -> A

%fix(Nat). (A : Type) -> A -> (%unroll !Nat -> A) -> A;
%fix(Nat). (A : Type) -> A -> (!Nat -> A) -> A;

| (tag : true, A)
| (tag : false, B)

Effect

type Return<A> =
  | { tag: "tail"; thunk: () => Return<A> }
  | { tag: "value"; return: A };

const $call = (x) => {
  while ($continue !== null) {
    x = $handler();
  }
  return x;
};

function* () {
  yield f(x);
}

f(x);

// TODO: benchmark against dumb function
// TODO: benchmark techniques such as full CPS to test engine inliners
$tail = true;
$continue = () => {};

const $apply = (x) => {
  while ($tail) {
    $tail = false;
    x = $continue();
  }
  return x;
};

$apply(f)(x);

let f = fun [@async] x -> 1

function kid(x, k) {
  return k(x);
}
function kid(x, k) {
  return $next(k, x);
}

let kid x k = k x
let rec rev acc l =
  match l with
  | [] -> acc
  | el :: tl -> rev (el :: acc) tl

Controlled Unfolding

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u)
  (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

u : %self(u). %unroll Unit (%fix(unit). u) u
  = %fix(u). P => (x : P (%fix(unit). u)) => x;


expected : %self(u). (P : (%self(u). %unroll Unit (%fix(unit). u) u) -> Type) -> P (%unroll (%fix(unit). u)) -> P u
received : %self(u). (P : (%self(u). %unroll Unit (%fix(unit). u) u) -> Type) -> P (%unroll (%fix(unit). u)) -> P (%unroll (%fix(unit). u))

expected : P u -> P u
received : P u -> P u

expected : P u -> P u
received : P u -> P u

(P : )
(P : (%self(u). Unit unit u) -> Type) -> P unit -> P u
Unit (%fix(unit). u) u


u : %self(u). Unit (%fix(unit). u) u =
  %fix(u). (P : (%self(u). Unit (%fix(unit). u) u) -> Type) => (x : P (%fix(unit). u)) => x;
unit2 : %self(unit). %self(u). Unit unit u = %fix(unit3). u;

expected : %self(u). Unit (%fix(unit3). u) u
received : %self(u). Unit (%fix(unit). u) u

expected : (P : (%self(u). Unit (%fix(unit). u) u) -> Type) -> P (%fix(unit). u) -> P (%fix(unit). u)
received : (P : (%self(u). Unit (%fix(unit). u) u) -> Type) -> P (%fix(unit). u) => P (%fix(unit). u)

expected : %self(u). Unit (%fix(unit). u) u
received : %self(u). Unit (%fix(unit). u) u;

fixunit (u : %self(u). Unit (unit u) u) = u;

x = %fix(u) : Unit (unit u) u. P => (x : P (unit u)) => x;

(P : (%self(u). Unit (unit b) u) -> Type) -> P b -> P b
(P : (%self(u). Unit (unit b) u) -> Type) -> P b -> P b

unit : %self(unit). %self(u). Unit unit u;



fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u) =
  (P : (%self(u). Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%unit = %fix(u) : Unit unit u. P => (x : P (%unroll unit)) => x;

fix%Unit (unit : %self(unit). %self(u). Unit unit u) (u : %self(u). Unit unit u) =
  (P : Unit unit u -> Type) -> P (%unroll (%unroll unit)) -> P (%unroll u);

fix%unit = %fix(u) : Unit unit u. P => (x : P (%unroll unit)) => x;

%fix(u). P => (x : P (%frozen unit)) => x

%self(u). (P : (%self(u). Unit unit u) -> Type) -> P (%fix(u). P => (x : P (%frozen unit)) => x) -> P (%fix(u). P => (x : P (%frozen unit)) => x)
%self(u). (P : (%self(u). Unit unit u) -> Type) -> P (%fix(u). P => (x : P (%frozen unit)) => x) -> P (%fix(u). P => (x : P (%frozen unit)) => x)

fix%Unit : Type = (
  fix%unit : Unit = (P : Unit -> Type) => (x : P unit) => x;
  %self(u). (P : Unit -> Type) -> (x : P unit) -> P u;
);

Unit : Type;
unit : Unit;

Unit = %self(u). (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x

fix%False (f : %self(f). False f) =
  (P : (%self(f). False f) -> Type) -> P f;

False = %self(f). False f;


Unit : %self(Unit). (u : %self(u). Unit u) -> Type;
unit : %self(u). Unit u;

Unit = u => (P : (%self(u). Unit u) -> Type) -> P unit -> P u;
unit = (P : (%self(u). Unit u) -> Type) => (x : P unit) => x;

%fix(u). P => x => x

%self(u). (P : (%self(u). Unit u) -> Type) -> P (%fix(u). P => x => x) -> P (%fix(u). P => x => x)
%self(unit). (P : (%self(u). Unit u) -> Type) -> P (%fix(u). P => x => x) -> P (%fix(u). P => x => x)


%fix(M : {
  Unit : %self(Unit). (u : %self(u). Unit u) -> Type;
  unit : %self(u). Unit u;
}). {
  Unit = (u : %self(u). M.Unit u) => (P : (%self(u). M.Unit u) -> Type) -> P M.unit -> P u;
  unit = (P : (%self(u). M.Unit u) -> Type) => (x : P M.unit) => x;
};

%fix(M : {
  Unit : Type;
  unit : Unit;
}). {
  Unit = %self(u).(P : (%self(u). M.Unit u) -> Type) -> P M.unit -> P u;
  unit = (P : (%self(u). M.Unit u) -> Type) => (x : P M.unit) => x;
};

fix%Unit = %self(u). (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P u;

%self(u). (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P u

u : %self(u). _A
Unit : Type


%self(u) : Unit. P => (x : P u) => x
%fix(u) : Unit. P => (x : P u) => x

%self(u). {A} {B}. A -> B -> B

expected : (P : (%self(u). Unit u) -> Type) -> P (%fix(u). P => x => x) -> P (%fix(u). P => x => x)
received : (P : (%self(u). Unit u) -> Type) -> P (%fix(u). P => x => x) -> P (%fix(u). P => x => x)


%self(unit). (P : (%self(u). Unit u) -> Type) -> P unit3 -> P unit
%self(unit2). (P : (%self(u). Unit u) -> Type) -> P unit2 -> P unit2
%fix(Unit : Type; unit : Unit). (
  %self(u). (P : Unit -> Type) -> P unit -> P u;
);

expected :

%self(a). (P : Unit -> Type) -> (x : P (%fix(c). P => (x : P c) => x)) -> P a
%self(b). (P : Unit -> Type) -> (x : P b) -> P b

(P : Unit -> Type) -> (x : P (%fix(c). P => (x : P c) => x)) -> P d
(P : Unit -> Type) -> (x : P d) -> P d


fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

T = %self(u). %unroll Unit (%fix(unit). u) u;

T = %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u

u : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u


fix%unit : %self(u). %unroll Unit unit u =
  %fix(u) : %unroll Unit (%fix(unit). u) u. P => x => x;

expected : %self(u). %unroll Unit unit u
received : %self(u). %unroll Unit (%fix(unit). u) u

expected : %self(unit). %self(u). %unroll Unit unit u
received : %self(unit). %self(u). %unroll Unit (%fix(unit). u) u

expected : %self(unit). %self(u). (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u
received : %self(unit). %self(u).
expected : %self(u). %unroll Unit (%fix(unit). u) u
received : (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u

%self(t). P (%unroll (%fix(x). t)) -> P t
%self(t). P (%unroll (%fix(x). t)) -> P (%unroll (%fix(x). t))

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

u : %self(u). %unroll Unit (%fix(unit). %fix(u). P => x => x) u
%unroll Unit (%fix(unit). %fix(u). P => x => x) u

%fix(unit). %fix(u) : %unroll Unit unit u. P => x => x

expected : P (%unroll unit) -> P (%fix(u). P => x => x)
received :
expected : %self(unit). %self(u). %unroll Unit unit u
received :
u : %self(u). %unroll Unit (%fix(unit). %fix(u). P => x => x) u
  = %fix(u). P => x => x;

unit : %self(unit). %self(k). %unroll Unit unit k = %fix(unit). u;

expected : %unroll Unit (%fix(unit). %fix(u). P => x => x) u
received : %unroll Unit (%fix(unit). %fix(u). P => x => x) u

expected : %unroll Unit (%fix(unit). %fix(u). P => x => x) u
received :

fix%unit : %self(u). %unroll Unit unit u =
  %fix(u) : %unroll Unit (%fix(unit). u) u. P => x => x;

expected : %self(u). %unroll Unit (%fix(unit). ) u
received : %self(u). %unroll Unit (%fix(unit). u) u


fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;


u : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u

expected : %self(u). %unroll Unit unit u
received : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u

%self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u

%fix(T). %self(u). %unroll Unit (%fix(unit) : %unroll T. u) u

u : %self(u). %unroll Unit (%fix(unit). u) u
  = %fix(u). P => x => x;

unit
  : %self(unit). %self(u). %unroll Unit unit u
  = %fix(unit). u;

expected : %self(u). %unroll Unit (%fix(unit). u) u
received : %self(u). %unroll Unit (%fix(unit). u) u

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

u : %self(u). %unroll Unit (%fix(unit). u) u
  = %fix(u). P => x => x;

unit
  : %self(unit). %self(u). %unroll Unit unit u
  = %fix(unit). u

u : %self(u). _A
unit : %self(unit). _B

_B : %self(u). _A
%self(unit). %self(u). _A : %self(unit). %self(u). %unroll Unit unit u


u : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u

expected : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u
received : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u


fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

u : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u
  = %fix(u). P => x => x;

unit = %fix(unit) : %self(u). %unroll Unit unit u. u;

Unit2 = %self(u). Unit unit u;

expected : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u
received : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u


unit = %fix(unit) : %self(u). %unroll Unit unit u.
  %fix(u). (P : (%self(u). %unroll Unit unit u) -> Type) => (x : P (%unroll unit)) => x

expected : %self(u). (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u
received : %self(k). (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P (%unroll unit);
%self(u). %unroll Unit (%fix(unit). %fix(u). P => x => x) u;

%unroll Unit ? u
u = %fix(u) : %unroll Unit ? u. P => x => x;
unit =


fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

u = %fix(u) : %unroll Unit (%fix(unit). u) (%fix(u). P => x => x). P => x => x;

%self(unit). %self(u). %unroll Unit unit (%fix(u) : %unroll Unit unit u. P => x => x)

expecected : %unroll Unit unit (%fix(u) : %unroll Unit unit u. P => x => x)
received : %unroll Unit unit unit

%self(u). %unroll Unit
  (%fix(unit) : %self(u). %unroll Unit unit (%fix(u). P => x => x). u)
  (%fix(u). P => x => x)

expected : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u
received : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) (%fix(u). P => x => x)

expected : %unroll Unit (%fix(unit). %fix(u). P => x => x) (%fix(u). P => x => x)
received : %unroll Unit (%fix(unit). %fix(u). P => x => x) (%fix(u). P => x => x)
expected : P u -> P (%fix(u). P => x => x)
received : P u -> P u

unit = %fix(unit) : %self(u). %unroll Unit unit u.
  %fix(u). P => x => x;

expected : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. %fix(u) : %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u. P => x => x) u
received : %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u. u) u

Unit2 = %self(u). Unit unit u;

Lambda Cube

Term =
  | Type
  | x
  | (x : Term) -> Term
  | (x : Term) => Term
  | Term Term;

-----------
Type : Type

A : Type  x : A
---------------
x : A

Γ, x : AB : Type
-------------------
Γ(x : A) -> B : Type

Γ, x : A ⊢ m : B
---------------------------
Γ(x : A) => m : (x : A) -> B

m : (x : A) -> B  n : A
-----------------------
Γ ⊢ m n : B[x := n]


PiSelf:

Term =
  | Type
  | x
  | (x : Term) -> Term
  | (x : Term) => Term
  | Term Term
  | %self(x). Term
  | %fix(x). Term
  | %unroll Term;

Γ, x : %self(x). TT : Type
-----------------------------
Γ ⊢ %self(x). T : Type

Γ, x : %self(x). T ⊢ m : T
----------------------------
Γ ⊢ %fix(x). m : %self(x). T

Γ ⊢ m : %self(x). T
-------------------------
Γ ⊢ %unroll m : T[x := m]


call f x = f x;

{N M A B}. (f : (x : A N) -> B M) -> (x : N) -> B M;

double = (x : Nat) : Nat => x + x;

id = (A : Type 0) => (x : A) => x;

Array : {
  @Array : Type;
  make : (n : Nat) -> $Array;
} = {

};

Socket : {
  @Socket : Type;
  connect : () -> $Socket;
  close : (socket : $Socket) -> ();
} = {};

List (A : Type) =

channel : Rc<Channel>;
2 buf : (socket : Socket, nat : Nat 15);

(A : Type)
Channel : {
  @Channel : Type;
  make : (n : Grade) -> Channel n;
} = {};

M : {
  double : (x : Nat) -> Nat;
} = {
  double = x => x + x;
}


%rec(f : Unit ->! Unit). f ()

Fix = %fix(Fix). Fix -> Never;

Unit = %fix(Unit).
  %self(u). (P : %unroll Unit -> Type) -> P (%fix(u). P => x => x) -> P u;

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;
unit : %self(unit). %self(u). %unroll Unit unit u = %fix(unit). %fix(u). P => x => x;


fix%False (f : %self(f). False f) = (P : False -> Type) -> P f;
False = %self(f). False f;


Unit = %self(u). Unit unit u;
unit : Unit = %unroll unit;

self%Unit : (self%u : %unroll Unit u) -> Type;
self%unit : %unroll Unit unit;

Unit (self%u : %unroll Unit u) = (P : (self%u : %unroll Unit u) -> Type) -> P unit -> P u;
unit = (P : (self%u : %unroll Unit u) -> Type) => (x : P unit) => x;

fix%M : {
  self%Unit : (self%u : %unroll Unit u) -> Type;
  self%unit : %unroll Unit unit;
} = {
  Unit (self%u : %unroll M.Unit u) = (P : (self%u : %unroll M.Unit u) -> Type) -> P M.unit -> P u;
  unit = (P : (self%u : %unroll M.Unit u) -> Type) => (x : P unit) => x;
};

(u : %self(u). %unroll Unit u) -> Type

expected : (P : (%self(u). %unroll Unit u) -> Type) -> P unit -> P unit
received : (P : (%self(u). %unroll Unit u) -> Type) -> P unit -> P unit

expected : %self(u). (P : %unroll Unit -> Type) -> P (%fix(u). P => x => x) -> P u
received : %self(u). (P : %unroll Unit -> Type) -> P (%fix(u). P => x => x) -> P u

expected : %self(u). (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P u
received : %self(u). (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P u

Value -> Value;
Type -> Value;
Type -> Type;
Value -> Type;

Consistency = Soundness + Strong Normalization;

(x : Int) => x;

Never = (A : Type) -> A;


id = (x : Int) => x;
id = (A : Type) => (x : A) => x;
Id = (A : Type) => A;

fold : (A : Type) -> (l : List A) ->
  (K : Type) -> (cons : K -> A -> K) -> (nil : K) -> K;

List A = (K : Type) -> (cons : K -> A -> K) -> (nil : K) -> K;
cons {A} el tl : List A = K => cons => nil => cons (tl K cons nil) el;
nil {A} el tl : List A = K => cons => nil => nil;

one_two_three = cons 1 (cons 2 (cons 3 nil));
one_two_three = K => cons => nil => cons (cons (cons nil 3) 2) 1;
x = one_two_three Int (acc => el => acc + el) 0;

if : (pred : Bool) -> (A : Type) -> (then : A) -> (else : A) -> A;

if pred return Int then 1 else 2
if pred return String then "a" else "b"

Bool = (A : Type) -> (then : A) -> (else : A) -> A

Unit = (A : Type) -> (x : A) -> A;
unit : Unit = A => x => x;

Bool = (A : Type) -> (then : A) -> (else : A) -> A;
true : Bool = (A : Type) => (then : A) => (else : A) => then;
false : Bool = A => then => else => else;

not : Bool -> Bool = pred => pred Bool false true;

Nat = (A : Type) -> (zero : A) -> (succ : A -> A) -> A;
zero : Nat = A => zero => succ => zero;
succ : Nat -> Nat = n => A => zero => succ => succ (n A zero succ);

Eq A x y = (P : A -> Type) -> P x -> P y;
refl A x : Eq A x x = (P : A -> Type) => (p : P x) => p;

Neq A x y = (eq : Eq A x y) -> Never;

_ : (n : Nat) -> Neq Nat n (succ n) = _;

_ : Eq Bool true (not false) = refl Bool true;

Eq Bool true true

call_id = (id : (A : Type) -> A -> A) => (id Int 1, id String "a");

fold : (n : Nat) -> (A : Type) -> A -> (A -> A) -> A;

nat_ind : (n : Nat) ->
  (P : Nat -> Type) -> P z -> ((pred : Nat) -> P pred -> P (s pred)) -> P n;

fold n A (z : A) (s : A -> A) = nat_ind n (_ => A) z (_ => s);

Nat =
  (P : Nat??? -> Type) -> P (z : Nat) -> ((pred : Nat???) -> P pred -> P (s pred)) -> P n???;



Unit = %fix(Unit).
  %self(u). (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P u;
unit : Unit = %fix(u). P => x => x;

Eq A x y = (P : A -> Type) -> P x -> P y;

%unroll unit : (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P unit

x = unit (_ => Int);

%self(u). (P : T -> Type) -> P u -> P u

(%fix(u). (P : T -> Type) => (x : P u) => x) :
  (P : T -> Type) -> P u -> P u;

(%unroll )

Nat = %fix()

forall P : nat -> Type,
  P 0 ->
  (forall n : nat, P n -> P (S n)) -> forall n : nat, P n

fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u) (u : %self(u). %unroll Unit unit u)
  = (P : (%self(u). %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;
unit : %self(unit). %self(u). %unroll Unit unit u = %fix(unit). %fix(u). P => x => x;

self%Unit : (self%u : %unroll Unit u) -> Type;
self%unit : %unroll Unit unit;

Unit (self%u : %unroll Unit u) =
  (P : (self%u : %unroll Unit u) -> Type) -> P unit -> P u;
unit = (P : (self%u : %unroll Unit u) -> Type) => (x : P unit) => x;

self%Bool : (self%b : %unroll Bool b) -> Type;
self%true : %unroll Bool true;
self%false : %unroll Bool false;

Bool (self%b : %unroll Bool b) =
  (P : (self%b : %unroll Bool b) -> Type) -> P true -> P false -> P b;
true = (P : (self%b : %unroll Bool b) -> Type) =>
  (then : P true) => (else : P false) => then;
false = (P : (self%b : %unroll Bool b) -> Type) =>
  (then : P true) => (else : P false) => else;

fix%False = %self(f). (P : False -> Type) -> P f;
fix%False (self%f : False f) = (P : (self%f : False f) -> Type) -> P f;


False = %fix(False). %self(f). (P : %unroll False -> Type) -> P f;

expected : %unroll False
received : %self(f). (P : %unroll False -> Type) -> P f

T = %fix(False). (self%f : %unroll False f) =>
  (P : (self%f : %unroll False f) -> Type) -> P f;

False = %self(f).
  (P : (self%f : %unroll (
    %fix(False). (self%f : %unroll False f) =>
      (P : (self%f : %unroll False f) -> Type) -> P f
  ) f) -> Type) -> P f;

False = %fix(False). %self(f). (P : %unroll False -> Type) -> P f;
False = %self(f). %unroll (
  %fix(False). (self%f : %unroll False f) =>
    (P : (self%f : %unroll False f) -> Type) -> P f
) f;

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

%self(Unit). (a : %self(b). %unroll Unit b b) ->
  (u : %self(u). %unroll Unit a u) -> Type;

%self(b). (%unroll Unit b) b

expecetd : %unroll Unit b c
received : %unroll Unit c c

%self(Unit). (a : %self(b). %unroll Unit b b) ->
  (u : %self(u). %unroll Unit a u) -> Type

%unroll Unit b

expected : %unroll Unit unit unit
received : %unroll Unit a unit

fix%Unit (self%unit : %unroll Unit unit unit)
  (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;


Unit = %self(u). %unroll (
  %fix(Unit). (self%u : %unroll Unit u) =>
    (P : (self%u : %unroll Unit u) -> Type) ->
    P (%fix(unit). P => (x : P unit) => x) ->
    P u
) u;

Unit = %fix(Unit).
  (P : %unroll Unit -> Type) -> P ? -> P u;
unit = %fix(unit) : %self(u). %unroll Unit unit u.
  %fix(u). P => (x : P (%unroll unit)) => (x : P u);

unit = ;

Unit1 = %fix(Unit1). (self%unit : %self(u). %unroll Unit1 unit u) => (self%u : %unroll Unit1 unit u) =>
  (P : (self%u : %unroll Unit1 unit u) -> Type) -> P (%unroll unit) -> P u;

Unit2 = %self(u). %unroll (
  %fix(Unit1). (self%unit : %self(u). %unroll Unit1 unit u) => (self%u : %unroll Unit1 unit u) =>
    (P : (self%u : %unroll Unit1 unit u) -> Type) -> P (%unroll unit) -> P u
) (%fix(A).?) u;

Unit2 = (
  (self%unit : %self(u). %unroll Unit1 unit u) => (self%u : %unroll Unit1 unit u) =>
    (P : (self%u : %unroll Unit1 unit u) -> Type) -> P (%unroll unit) -> P u
) (%fix(unit). );

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

expected : %unroll (
    %fix(False). (self%f : %unroll False f) =>
      (P : (self%f : %unroll False f) -> Type) -> P f
  ) f
expected : (P : (self%f : %unroll (
    %fix(False). (self%f : %unroll False f) =>
      (P : (self%f : %unroll False f) -> Type) -> P f
  ) f) -> Type) -> P f
received : (P : (self%f : %unroll (
    %fix(False). (self%f : %unroll False f) =>
      (P : (self%f : %unroll False f) -> Type) -> P f
  ) f) -> Type) -> P f

expected : (P : (self%f : %unroll T f) -> Type) -> P f
received : (P : (self%f : %unroll T f) -> Type) -> P f

%self(f). %unroll (%(P : %unroll False -> Type) -> P f)

expected : %unroll False
received : %self(f). %unroll (%fix(False). (P : %unroll False -> Type) -> P f)

False = %self(f).
  (P : (f : %self(f). %unroll (
    %fix(False). (P : ? -> Type) -> P f;
  )) -> Type) -> P f;

expected : %self(f). (P : (self%f : %unroll False f) -> Type) -> P f
received : %self(f). (P : (self%f : %unroll False f) -> Type) -> P f

fix%Unit (self%u : %unroll Unit u) =
  (P : (self%u : %unroll Unit u) -> Type) -> P unit -> P u;

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%Unit (self%unit : %self(u). %unroll Unit unit (%unroll unit)) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

// needs to expand unit inside of unit
fix%unit : %self(u). %unroll Unit unit u =
  %fix(u). P => (x : P (%unroll u)) => x;


fix%unit (u : %self(u). %unroll Unit unit u)
  : %self(u). %unroll Unit unit u =
  P => (x : P (%unroll unit)) => (x : P u);

u = %fix(u) : %unroll Unit unit u. %unroll unit u;

expected : %unroll Unit unit u
received :

fix%unit : %self(u). %unroll Unit unit (%fix(u) : %unroll Unit unit u. P => (x : ) => ) =
  %fix(u). P => (x : P (%unroll unit)) => (x : P (%unroll unit));

%self(u). %unroll Unit (%fix(unit). u) u

expected : %unroll Unit unit u
received : (P : (self%u : %unroll Unit unit u) -> Type) -> P u -> P u

expected : %self(u). (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u
received : %self(u). (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P (%unroll unit)
fix%u : %unroll Unit unit u
  = (P : (self%u : %unroll Unit unit u) -> Type) =>
    (x : P (%unroll unit u)) => (x : P u)

Unit = %self(u). Unit unit u;
expected : P (%unroll unit u) -> P u
received : P u -> P u
fix%unit : %self(u). %unroll Unit unit u =
  %fix(u). P => (x : P (%unroll unit)) => (x : P u);

expected : (x : P (%fix(u). P => x => x)) -> P u
received : (x : P u) -> P u;
expected : %self(u). (P : (self%u : %unroll Unit unit u) -> Type) -> P unit -> P u
received : %self(u). (P : (self%u : %unroll Unit unit u) -> Type) -> P u -> P u

fix%unit (self%u : %unroll Unit (%unroll unit u) u) =
  (P : (self%u : %unroll Unit (%unroll unit u) u) -> Type) =>
  (x : P (%unroll unit u)) => (%unroll u P x : P u);

u : %self(u). %unroll Unit (%unroll unit u) u
  = %fix(u). %unroll unit u;


fix%unit : %self(u). %unroll Unit unit u =


expected : (P : (self%u : %unroll Unit u) -> Type) -> P unit -> P unit
received : (P : (self%u : %unroll Unit u) -> Type) -> P unit -> P unit


fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

%self. (%self. %unroll \1 \0 \0) -> (%self. %unroll \2 \1 \0) -> Type;

%self(Unit). (a : %self(b). %unroll Unit b b) -> (c : %self(d). %unroll Unit a d) -> Type;


(%unroll Unit : (a : %self(b). %unroll Unit b b) -> (c : %self(d). %unroll Unit a d) -> Type) b b
(%unroll Unit b : (c : %self(d). %unroll Unit b d) -> Type) b



%fix. (%self. %unroll \1 \0 \0) => (%self. %unroll \2 \1 \0) =>
  ((%self. %unroll \3 \2 \0) -> Type) -> \0 \2

(\0 : (%self. %unroll \3 \2 \0) -> Type) (\2 : %self. %unroll \3 \0 \0)

expected : %unroll \3 \2 \2
received : %unroll \3 \2 \2
fix%Unit (self%unit : %unroll Unit unit unit) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%Unit (a : %self(b). %unroll Unit b b) (c : %self(d). %unroll Unit a d) =
  (P : (e : %self(f). %unroll Unit a f) -> Type) -> P (%coerce a) -> P u;

Γ ⊢ m : %self(x). T
-------------------------
Γ ⊢ %unroll m : T[x := m]

Γ ⊢ m : %self(x). A   A[x := m] == B[x := m]
--------------------------------------------
Γ ⊢ %coerce m : %self(x). B

(%unroll (%coerce m : B))
fix%Unit (self%unit : %unroll Unit unit unit) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

unit : %self(u).
%coerce (x => %self(y). %unroll Unit x y)

unit : %self(b). %unroll Unit b b = %fix(b). P => x => x;

expected :
expected : %unroll Unit unit (%unroll u)
received :


self%Unit : (self%u : %unroll Unit u) -> Type;
self%unit : %unroll Unit unit;

Unit (self%u : %unroll Unit u) =
  (P : (self%u : %unroll Unit u) -> Type) -> P unit -> P u;
unit =

(f : rec F. F -> ()) => f(f);

rec F. F -> ()
(rec F. F -> ()) -> ()
((rec F. F -> ()) -> ()) -> ()

fix = f => f (fix f);

y = fix fix;

map map = f => l => (l | [] -> [] | el :: tl -> f el :: map map f l);


map = (f => f (fix f)) (fix (f => f (fix f)))  map;

map = (f => f (fix f)) map;


[]

y = f => (x => f(x(x)))(x => f(x(x)));
z = f => (x => f(v => x(x)(v)))(x => f(v => x(x)(v)));

z(self => 1);


double = x => x + x;

double((() => {
  console.log("hi");
  return 1;
})())

double(1)
1 + 1

map2 = map map;


(f => f f)(f => f f)
l = map map (+ 1) [1, 2, 3];
l = (+ 1) 1 :: (+ 1) 2 :: (+ 1) 3 :: [];

map = map map [1, 2, 3];

Unit = %self(u). Eq Unit unit u;


False = %fix(False). %self(f). (P : %unroll False -> Type) -> P f
False = %self(f). %unroll (
  %fix(False). (f : %self(f). %unroll False f) =>
    (P : (f : %self(f). %unroll False f) -> Type) -> P f;
) f;

fix%M : {
  Unit : %self(Unit). (u : %self(u). %unroll Unit u) -> Type;
  unit : %self(u). %unroll Unit u;
} = {
  Unit (u : %self(u). %unroll M.Unit u) =
    (P : (u : %self(u). %unroll M.Unit u) -> Type) -> P M.unit -> P u;
  unit = (P : (u : %self(u). %unroll M.Unit u) -> Type) => (x : P M.unit) => x;
};

ind_unit : (u : Unit) -> (P : Unit -> Type) -> P unit -> P u;
Unit = (P : Unit -> Type) -> P unit -> P u;

False = %fix(False). %self(f).
  (P : %unroll False -> Type) -> P f;

expected : %unroll False;
received : %self(f). (P : %unroll False -> Type) -> P f;


Unit = %ind(Unit, unit : Unit);

fix%False = %self(f). (P : %unroll False -> Type) -> P f;

fix%Unit =
  %self(u). (P : %unroll Unit -> Type) -> P (%fix(u). P => (x : P u) => x) -> P u;

expected : %self(u). (P : %unroll Unit -> Type) -> P (%fix(u). P => (x : P u) => x) -> P u
received : %self(u). (P : %unroll Unit -> Type) -> P (%fix(u). P => (x : P u) => x) -> P u;
fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%unit : %self(u). %unroll Unit unit u.
  %fix(u). P => (x : P (%unroll unit)) => (x : P u);


P (%unroll unit) == P u;

%unroll unit = u


%fix(unit). P => x => x;
%unroll unit ()
%self().

Unit =

x => y => x
lambda. lambda. \1

x => y => y
lambda. lambda. \0

Teika -> JS
Teika -> Smol

expected : %unroll False
received : %self(f). (P : %unroll False -> Type) -> P f

False = %fix(False). %self(f). (P : False -> Type) -> P f;
f : False;



(P : False -> Type) -> P f

expected : %self(f). (P : False -> Type) -> P f;
received : %self(f). (P : False -> Type) -> P f;

(n : Nat) =>
  n |

Generics

incr = x => x + 1;

(x => x + 1)

1 + 1 -> generalizes to (x => x + 1) ->

(x => x + 1)(1)

(1 + 1)

(x => x + 1)(2)

(2 + 1)

x => x + 1

(x => M)(N) === M[x := N]
(<A>M)<N> === M[A := N]

(x => x + 1)(1) === (x + 1)[x := 1] => 1 + 1


incr = (x : Int) => x + 1;

id_int = (x : Int) => x;
id_string = (x : String) => x;

((x : Int) => x)


id = <A>(x : A) => x;
id_int = id<Int>;
id_int = (x : Int) => x;
id_string = (x : String) => x;

Row Tuples

Array A = (n : Nat, ...(n _ (acc => A :: acc) []));

Two Step Fixpoint

False = %fix(False). %self(f). (P : %unroll False -> Type) -> P f;

%fix(T,
  T_eq : %self(T_eq). Eq Type (%unroll T)
    (Eq _
      (%fix(False, eq : %unroll T). %self(f).
        (P : %unroll False -> Type) -> P (%unroll (T_eq (X => X) eq) (False => %unroll False) f)) False)
).
  Eq _ (%fix(False, eq : %unroll T). %self(f).
        (P : %unroll False -> Type) -> P (%unroll (T_eq (X => X) eq) (False => %unroll False) f)) False;

False_Eq False = %self(eq). %unroll (%fix(Eq_T, self%Eq_T_eq :
  Eq _ (%unroll T)
    (Eq _ (%fix(False, eq : %unroll T). %self(f). (P : %unroll False -> Type) ->
      P (%unroll (%unroll Eq_T_eq (X => X) eq) (False => %unroll False) f)
    ) False)
).
  Eq _ (%fix(False, eq : %unroll T). %self(f). (P : %unroll False -> Type) ->
    P (%unroll eq (False => %unroll False) f)
  ) False;
);

False = %fix(False,
  eq
    : %self(eq). Eq _ (%self(f). (P : %unroll False -> Type) -> P (%unroll eq (X => X) f)) (%unroll False)
    = %fix(eq). P => (x : P (%self(f). (P : %unroll False -> Type) -> P (%unroll eq (X => X) f))) => x
).
  %self(f). (P : %unroll False -> Type) -> P (%unroll eq (X => X) f)

Body_T =
  %self(Body). (X : %self(X). Type) -> (X_eq _ (%unroll Body X X_eq) (%unroll X)) -> Type;
Make_eq_unroll
  (First : )
  (Second : Body_T) =
  %fix(X, X_eq : %self(X_eq). Eq _ (%unroll Body X X_eq) (%unroll X)).
    %unroll Body X X_eq;

False = Make
  ()
  (False => False_eq =>
    %self(f). (P : False -> Type) -> P (%unroll False_eq (X => X) P))
x = Make_eq_unroll (%fix(Body, ()). False => False_eq =>
  %self(f). (P : False -> Type) -> )


Eq_T_eqT (self%Eq_T : (False : %self(False). Type) -> Type) =
  %self(Eq_T_eq). (False : %self(False). Type) ->
    Eq _ (%unroll Eq_T False) (
      Eq _ (%fix(False, False_eq : %unroll Eq_T False).
        %self(f). (P : %unroll False -> Type) ->
          P ((%unroll Eq_T_eq False (X => X) False_eq) (False => %unroll False) f)
      ) False
    );
False_EqT =
  %fix(
    Eq_T,
    Eq_T_eq
      : %self(Eq_T_eq). (False : %self(False). Type) ->
          Eq _ (%unroll Eq_T False) (
            Eq _ (%fix(False, False_eq : %unroll Eq_T False).
              %self(f). (P : %unroll False -> Type) ->
                P ((%unroll Eq_T_eq (X => X) False_eq) (False => %unroll False) f)
            ) False
          )
      = _
  ). False =>
  Eq _ (%fix(False, False_eq : %unroll Eq_T). %self(f). (P : %unroll False -> Type) ->
    P (%unroll (%unroll Eq_T_eq (X => X) False_eq) (False => %unroll False) f)
  ) False;


%fix(False, self%eq : %unroll (%fix(Eq_T, self%Eq_T_eq :
  Eq _ (%unroll T)
    (Eq _ (%fix(False, eq : %unroll T). %self(f). (P : %unroll False -> Type) ->
      P (%unroll (%unroll Eq_T_eq (X => X) eq) (False => %unroll False) f)
    ) False)
).
  Eq _ (%fix(False, eq : %unroll T). %self(f). (P : %unroll False -> Type) ->
    P (%unroll eq (False => %unroll False) f)
  ) False;
)).

False = %fix(False)(
  self%eq : Eq Type (%self(f). (P : %unroll False -> Type) -> P (%unroll eq P f))
    (%unroll False)
    = (P : Type -> Type) => (x : P (%self(f). (P : %unroll False -> Type) -> P (%unroll eq P f))) => x;
). %self(f). (P : %unroll False -> Type) -> P (%unroll eq P f);

Unit = %fix(Unit, eq).
  %self(u). (P : %unroll Unit -> Type) ->
    P (%fix(u))
    P (%unroll eq P u)

Unit = %fix(Unit, Unit_eq). %self(u).
  (P : %unroll Unit -> Type) ->
  P (%fix(unit, unit_eq) : %unroll Unit.
    (P : %unroll Unit -> Type) => (x : P unit) => x
    ) ->
  P (%unroll Unit_eq P u);
Unit = %fix(Unit, eq). (self%unit : %self(u). %unroll Unit unit u) => (self%u : %unroll Unit unit u) =>
  (P : (self%u : %unroll Unit unit u) -> Type) ->
    P (%unroll unit) -> P u;

unit = %fix(unit, unit_eq) : Unit unit.
  %fix(u, _). P => (x : P (%unroll unit)) =>
    (unit_eq P )

False = %fix(False,
  eq : Eq _ False (fix(False, ))
  ). %self(f).
fix%Unit (unit : %self(unit). %self(u). %unroll Unit unit u)
  (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

unit = %fix(unit, ).
  %fix(u)(
    eq : Eq _ (%unroll unit) u = P => (x : P (%unroll unit)) =>
  ) : %unroll Unit unit u.
    P => (x : P (%unroll unit)) => eq P x;

(P : (self%u : Unit unit u) -> Type) => (x : P (%unroll unit)) => x
fix%T =
  %self(eq).
    Eq (%self(unit). %self(u). Unit unit u) unit
      (%fix(unit, eq : T). %fix(u, ()) : Unit unit u.
    P => x => (eq (unit => P (%unroll unit)) x : P u))

fix%Unit (self%u : %unroll Unit u) : Type =
  (P : (self%u : %unroll Unit u) -> Type) ->
  P (%fix(u) : %unroll Unit u. P => (x : P u) => x) -> P u

fix%Unit (self%u : %unroll Unit u) : Type =
  (P : (self%u : %unroll Unit u) -> Type) ->
  P (%fix(u) : %unroll Unit u. P => (x : P u) => x) -> P u

TUnit = %self(Unit). (self%u : %unroll Unit u) -> Type;
Tunit_eq (Unit : TUnit) (self%u : %unroll Unit u) =
  Eq Type ((P : (self%u : %unroll Unit u) -> Type) -> P u -> P u) (%unroll Unit u);

TUnit_eq (Unit : TUnit) = %self(Unit_eq). (self%u : %unroll Unit u) ->
  Eq Type (
    (P : (self%u : %unroll Unit u) -> Type) ->
    P (%fix(u, u_eq : Tunit_eq Unit u = Unit_eq u).
        u_eq (X => X) (P => x => x)) ->
    P u
  ) (%unroll Unit u);

Unit = %fix(Unit, Unit_eq : TUnit_eq Unit = %fix(Unit_eq). P => x => x).
  (self%u : %unroll Unit u) =>
  (P : (self%u : %unroll Unit u) -> Type) ->
  P (%fix(u, u_eq : Tunit_eq Unit u = Unit_eq u).
      u_eq (X => X) (P => x => x)) ->
  P u;

Unit = %self(u). %unroll Unit u;
unit : Unit = %fix(u, u_eq : Tunit_eq Unit u = Unit_eq u).
      u_eq (X => X) (P => x => x);


expected : (P : _) -> P u -> P u
received : %unroll Unit u



case : (b : Bool) -> (A : Type) -> A -> A -> A;
Bool = (A : Type) -> A -> A -> A;

ind_bool : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
Bool = %self(b). (P : Bool -> Type) -> P true -> P false -> P b;

T_False_eq False =
  %self(False_eq). Eq Type
    (%self(f). (P : %unroll False -> Type) -> P (%unroll False_eq (X => X) f))
    (%unroll False);

False_eq : %self(False_eq). Eq Type
  (%self(f). (P : %unroll False -> Type) -> P (%unroll False_eq (X => X) f))
  (%unroll False);


%fix(False,
  False_eq : %self(False_eq). Eq Type (%self(f). (P : %unroll False -> Type) -> P (%unroll False_eq (X => X) f)) (%unroll False)
    = %fix(False_eq). P => x => x).
  %self(f). (P : %unroll False -> Type) -> P (%unroll False_eq (X => X) f);


%self(False_eq). Eq Type
  (%self(f). (P : %unroll False -> Type) -> P (%unroll False_eq (X => X) f))
  (%self(f). (P : %unroll False -> Type) -> P (%unroll False_eq (X => X) f))


%fix(Fix). (x : %unroll Fix) -> Fix;

Unit : {
  Unit : Type;
  unit : Unit;
  ind_unit : (u : Unit) -> (P : Unit -> Type) -> P unit -> P u;
} = {};
(Unit, unit, ind_unit) = (
  fix%Unit = %self(u). (P : Unit -> Type) -> P (%fix(u). P => x => x) -> P u;
  unit = %fix(u). P => x => x;
  ind_unit = u => %unroll u;
  (Unit, unit, ind_unit);
);

((u : Unit) => ind_unit u (_ => Nat) 1) unit;


TUnit = %self(Unit). (self%u : %unroll Unit u) -> Type;
Tunit_eq (Unit : TUnit) (self%u : %unroll Unit u) =
  Eq Type ((P : (self%u : %unroll Unit u) -> Type) -> P u -> P u)
    (%unroll Unit u);

TUnit_eq (Unit : TUnit) = %self(Unit_eq). (self%u : %unroll Unit u) ->
  Eq Type (
    (P : (self%u : %unroll Unit u) -> Type) ->
    P (%fix(u, u_eq : Tunit_eq Unit u = %unroll Unit_eq u).
        u_eq (X => X) (P => x => x)) ->
    P u
  ) (%unroll Unit u);

Tunit_eq (Unit : TUnit) (self%u : %unroll Unit u) =
  Eq Type (P u -> P u)
    (%unroll Unit u);


%fix(u, u_eq : Tunit_eq Unit u = ).
  P => u_eq (u => P u -> P u) (x => x);

Unit = %fix(Unit, Unit_eq : TUnit_eq Unit = %fix(Unit_eq). P => x => x).
  (self%u : %unroll Unit u) =>
  (P : (self%u : %unroll Unit u) -> Type) ->
  P (%fix(u, u_eq : Tunit_eq Unit u = %unroll Unit_eq u).
      u_eq (X => X) (P => x => x)) ->
  P u;



Unit = %fix(Unit, Unit_eq : TUnit_eq Unit = %fix(Unit_eq). P => x => x).
  (self%u : %unroll Unit u) =>
  (P : (self%u : %unroll Unit u) -> Type) ->
  P (%fix(u, u_eq : Tunit_eq Unit u = %unroll Unit_eq u).
      u_eq (X => X) (P => x => x)) ->
  P u;

Unit = %self(u). %unroll Unit u;
unit : Unit = %fix(u, u_eq : Tunit_eq Unit u = Unit_eq u).
      u_eq (X => X) (P => x => x);

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;
unit : %self(unit). %self(u). %unroll Unit unit u =
  %fix(unit,
    self%eq : Eq _ (%unroll unit) (%fix(u, ()). P => x => eq P x)
      = P => x => x
  ). %fix(u, ()). P => x => eq P x;

Unit = %self(u). %unroll Unit unit u;
unit : Unit = %unroll unit;

fix%Bool
  (self%true : (self%false : %self(b). %unroll Bool true false b) ->
    %self(b). %unroll Bool true false b)
  (self%false : %self(b). %unroll Bool true false b)
  (self%b : %unroll Bool true false b) =
  (P : (self%b : %unroll Bool true false b) -> Type) ->
    P (%unroll true false) -> P (%unroll false) -> P b;

true : (self%false : %self(b). %unroll Bool true false b) -> %self(b). %unroll Bool true false b =
  %fix(true,
    self%eq : Eq _ (%unroll true false) (%fix(b, ()). P => x => y => eq P x)
      = P => x => x;
  ). false => %fix(b, ()). P => x => y => eq P x;
false : %self(false). %self(b). %unroll Bool true false b =
  %fix(false,
    self%eq : Eq _ (%unroll false) (%fix(b, ()). P => x => y => eq P y)
      = P => x => x;
  ). %fix(b, ()). P => x => y => eq P y;

Bool = %self(b). %unroll Bool true false b;

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;
unit : %self(unit). %self(u). %unroll Unit unit u =
  %fix(unit,
    self%eq : Eq _ (%unroll unit) (%fix(u, ()). P => x => %unroll eq P x)
      = %fix(eq). P => x => x
  ). %fix(u, ()). P => x => %unroll eq P x;

Unit = %self(u). %unroll Unit unit u;
unit : Unit = %unroll unit;

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;
unit : %self(unit). %self(u). %unroll Unit unit u =
  %fix(unit, eq). %fix(u, ()). P => x => %unroll eq P x;

Unit = %self(u). %unroll Unit unit u;
unit : Unit = %unroll unit;

T_unit =
  %self(unit).
    (self%unit_eq :
      Eq _ (%unroll unit) (%fix(u). P => x => %unroll unit_eq P x)) ->
    %self(u). %unroll Unit (%fix(unit) : %self(u). %unroll Unit unit u) u;

unit : T_unit.
  = %fix(unit). unit_eq => %fix(u). P => (x : P unit) => %unroll unit_eq P x;



expected : (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u
received : (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P (%fix(self%u : %unroll Unit unit u, ()). P => x => unit_eq P x)

Eq _ ((P : (self%u : %unroll Unit unit u) -> Type) -> P u -> P u)
((P : (self%u : %unroll Unit unit u) -> Type) -> P u -> P u))



Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, x : %self(x). T,
  eq : %self(eq). (P : T -> Type) -> P (%unroll x) -> P M |- M : T[x := M]
--------------------------------------------------------------------------
%fix(self%x : T, eq). M : %self(x). T

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]

---------------------------------------------------
%unroll (%fix(self%x : T, eq). M) ===
M[x := %fix(self%x : T, eq). M]
 [eq := %fix(eq, _). (P : T -> Type) => (x : P M) => x]


fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;
unit : %self(unit). %self(u). %unroll Unit unit u =
  %fix(unit, eq). %fix(u, _). P => x => %unroll eq P x;

Unit = %self(u). %unroll Unit unit u;
unit : Unit = %unroll unit;

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, x : %self(x). T, y : A |- M : T[x := M]
Γ, x : %self(x). T |- N : A[x := %fix(self%x : T, y : A = N). M]
----------------------------------------------------------------
%fix(self%x : T, y : A = N). M : %self(x). T

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]


fix%Bool
  (self%true : (self%false : %self(b). %unroll Bool true false b) ->
    %self(b). %unroll Bool true false b)
  (self%false : %self(b). %unroll Bool true false b)
  (self%u : %unroll Bool true false b) =
  (P : (self%u : %unroll Bool true false b) -> Type) ->
    P (%unroll true false) -> P (%unroll false) -> P b;

unit : %self(true). (self%false : %self(b). %unroll Bool true false b) -> %self(b). %unroll Bool true false b =
  %fix(unit, eq). %fix(u, _). P => x => %unroll eq P x;

fix%Nat
  (self%zero : (self%succ : %self(n). %unroll Nat zero succ n) ->
    %self(n). %unroll Nat zero succ n)
  (self%succ : (pred : %self(n). %unroll Nat zero succ n) ->
    %self(n). %unroll Nat zero succ n) ->
  (self%n : %unroll Nat zero succ n) =
    (P : (self%n : %unroll Nat zero succ n) -> Type) ->
    P (%unroll zero succ) ->
    ((pred : %self(n). %unroll Nat zero succ n) -> P pred -> P (%unroll succ pred)) ->
    P n;

zero
  : %self(zero). (self%succ : %self(n). %unroll Nat zero succ n) -> %self(n). %unroll Nat zero succ n
  = %fix(zero, eq). succ => %fix(b, _). P => z => s => %unroll eq (b => P (b succ)) z;

unit : %self(unit). %self(u). %unroll Unit unit u =
  %fix(unit, eq). %fix(u, _). P => x => %unroll eq P x;

T_F_eq = Eq
  _
  (%fix(False, F_eq : ?))
%fix(False, F_eq).
  %self(f). (P : %unroll False -> Type) -> P (F_eq (False => %unroll False) f);
Unit = %fix(Unit, U_eq).
  %self(u).
  (P : %unroll Unit -> Type) ->
  P (
    %fix(unit, u_eq).
      P => eq_sym u_eq (u => P u -> P unit) (x => x)
  ) ->
  P (U_eq (Unit => %unroll Unit) u);

%fix((true, false), (T_eq, F_eq))
Bool = %fix(Bool, B_eq).
  %self(b).
    (P : %unroll Bool -> Type) ->
    P (
      %fix(true, b_eq).
        P => eq_sym b_eq (b => P b -> P false -> P true) (x => y => x)
    ) ->
    P (
      %fix(true, b_eq).
        P => eq_sym b_eq (b => P b -> P false -> P true) (x => y => x)
    ) ->
    P (U_eq (Unit => %unroll Unit) u)

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;
unit : %self(unit). %self(u). %unroll Unit unit u =
  %fix(unit). %fix(u). P => x => eq P x;


%unroll (%fix(T). (self%x : %unroll T x) => Type);


u @-> (P : (a : u @-> @((Unit : Unit @-> (unit : unit @-> u @-> @Unit unit u) -> (u : u @-> @Unit unit u) -> Type, _) @=> (unit : unit @-> u @-> @Unit unit u) => (u : u @-> @Unit unit u) => (P : (a : u @-> @Unit unit u) -> Type) -> (b : P (@unit)) -> P u) unit u) -> Type) -> (b : P (@unit)) -> P u :
u @-> @((Unit : Unit @-> (unit : unit @-> u @-> @Unit unit u) -> (u : u @-> @Unit unit u) -> Type, _) @=> (unit : unit @-> u @-> @Unit unit u) => (u : u @-> @Unit unit u) => (P : (a : u @-> @Unit unit u) -> Type) -> (b : P (@unit)) -> P u) unit u


(FalseT : Type) = %self(False). (f : %self(f). %unroll False f) -> Type;
False0 = %fix(False : FalseT).
  f => (P : (f : %self(f). %unroll False0 f) -> Type) -> P f;
False1 = %self(f). %unroll False0 f;

eq : (F : _) ->
    Eq _ (%unroll False0)
      (f => (P : (f : %self(f). %unroll False0 f) -> Type) -> P f)
  = _;

f (f : False1) : %self(f). (P : (f : %self(f). %unroll False0 f) -> Type) -> P f
  = eq (T => %self(f). (P : (f : %self(f). T f) -> Type) -> P f) f;

expected : %self(f). %unroll False0 f
received : %self(f). (P : (f : %self(f). %unroll False0 f) -> Type) -> P f;

expected : %self(f). %unroll False0 f
received : %self(f). (P : (f : %self(f). %unroll False0 f) -> Type) -> P f;

eq : (F : _) ->
    Eq _ (%unroll (%fix(x, eq). F x eq))
      (F (%fix(x, eq). F x eq) refl)
  = P => (x : P (%unroll (%fix(x, eq). F x eq))) =>
    ;



W : %self(W). (x : %self(x). %unroll W x) -> Type;
F :
  %self(F).
    (x : %self(x). %unroll W x) ->
    (eq :
      %self(eq). (P : %unroll W x -> Type) ->
        P (%unroll x) -> P (%unroll F x eq)) ->
    %unroll W x;
%fix_red :
  (W : %self(W). (x : %self(x). %unroll W x) -> Type) ->
  (F : %self(F).
    (x : %self(x). %unroll W x) ->
    (eq :
      %self(eq). (P : %unroll W x -> Type) ->
        P (%unroll x) -> P (%unroll F x eq)) ->
    %unroll W x) ->
  (P : (x : W (%fix(self%x : %unroll W x, eq). %unroll F x eq)) -> Type) ->
  P (%unroll (%fix(self%x : %unroll W x, eq). %unroll F x eq))
  P (%unroll F (%fix(self%x : %unroll W x, eq). F x eq) refl);

%fix_red(%fix(self%x : T, eq). M) : %self(x). T

%fix_red(
  x = %fix(self%x : T, eq). M,
  _ : (P : (a : %self(x). T) -> Type) ->
      P (%unroll (%fix(self%x : T, eq). M)) ->
      P x
);

%fix_red(
  x = %fix(self%x : T, eq). M,
  _ : (P : (a : %self(x). T) -> Type) ->
      P (%unroll (%fix(self%x : T, eq). M)) ->
      P x
) ===
  (P : (a : %self(x). T) -> Type) =>
    (b : P (%unroll (%fix(self%x : T, eq). M))) =>
    (b : P (M[x := %fix(self%x : T, eq). M][y := refl]));

Γ |- M : %self(x). T
Γ, x : %self(x). T |- A : Type Γ |- N : A[x := M]

A[a := %unroll M]
A[a := M[]]
---------------------------------------
%fix_red(x = M, eq : A = N) :
  A[x := ]

%self(%fix(x, eq). %unroll F x eq)
(%unroll (%fix(x, eq). F x eq))
F (%fix(x, eq). F x eq) refl
F => Eq _
  (%unroll (%fix(x, eq). F x eq))
  (F (%fix(x, eq). F x eq) refl)

%fix_red (

)

id = (x : Int) => x;

f = P => (x : P (id 1)) => (x : P 1);
g = P => (x : P (id 1)) => (%beta x : P 1);

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

unit_expand (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : Type -> Type) => (x : P (%unroll Unit unit u)) => %expand x;

unit : %self(unit). (eq : _) -> %self(u). %unroll Unit unit u
  %fix(unit). (eq : _) => %fix(u). P => x => eq P x;

unit : %self(unit). %self(u). %unroll Unit unit u =
  %fix(unit, eq). %fix(u, _).
    eq_sym (unit_expand unit u) (X => X) (P => x => eq P x);

unit : %self(unit). %self(u). %unroll Unit unit u =
  %fix(unit, eq). %fix(u, _). P => x => x;

id = (x : Int) => %expand x;

x = (x : P (id 1)) => %beta x ==;

(%unroll (%fix(x, eq). M)) === M[x := %fix(x, eq). M][eq := refl]

%expand x === x

Id = X => X;
fix%False (self%I : (self%f : (P : %unroll False I -> Type) -> P (I f)) -> %unroll False I) =
  %self(f). (P : %unroll False I -> Type) -> P (I f);
False = %unroll False (%fix(I). P => x => x);

fix%Unit (self%unit : %self(u). %unroll Unit unit u) (self%u : %unroll Unit unit u) =
  (P : (self%u : %unroll Unit unit u) -> Type) -> P (%unroll unit) -> P u;

fix%Unit (I1 : Eq _ (%unroll Unit) _) (self%unit : %unroll Unit I1 unit) = (
  W (P : %unroll Unit I1 -> Type) = I1 (U => U I1 -> Type) P;
  %self(u). (P : %unroll Unit I1 unit -> Type) -> W P (%unroll unit) -> W P u
);


fix%Unit (I1 : Eq _ (%unroll Unit I1) _) = (
  W (P : %unroll Unit I1 -> Type) = I1 (U => U -> Type) P;
  fix%unit (I2 : _) = %fix(u). I2 (P => (x : W P (%unroll unit I2)) => x);
  unit = %unroll unit (%fix(I2).
    (x : ((P : )))
  )
  %self(u). (P : %unroll Unit I1 -> Type) ->
    W P (%unroll unit) -> W P (u)
);

!Unit ===
  %self(u). (P : %unroll Unit I_Unit unit I_unit -> Type) ->
    %unroll I_Unit unit I_unit P (%unroll unit I_unit) ->
    %unroll I_Unit unit I_unit P u;
!T_I_Unit ===
  %self(I_Unit). (unit : !T_unit) -> (I_unit : !T_I_unit) ->
    (P : %unroll Unit I_Unit unit I_unit -> Type) -> !Unit -> Type;
!T_unit ===
  %self(unit). (I_unit : !T_I_unit) -> !Unit;
!T_I_unit ===
  %self(I_unit). (P : %unroll Unit I_Unit unit I_unit -> Type) ->
    P (%unroll unit I_unit) -> P !unit;
!unit ===
  %fix(u). (P : %unroll Unit I_Unit unit I_unit -> Type) =>
    (x : P (%unroll unit I_unit)) => %unroll I_unit P x;

fix%Unit (I_Unit : !T_I_Unit) (unit : !T_unit) (I_unit : !T_I_unit) : Type = !Unit;
I_Unit : !T_I_Unit = %fix(I_Unit). unit => I_unit => P => %expand P;

fix%unit (I_unit : !T_I_unit) : !Unit = !unit;
I_unit : !T_I_unit = %fix(I_unit). P => %expand P;

Unit = %unroll Unit I_Unit unit I_unit;

!Unit ===
  %self(u). (P : %unroll Unit I_Unit unit I_unit -> Type) ->
    P (%unroll unit I_unit) -> %unroll I_Unit unit I_unit P u;
!T_I_Unit ===
  %self(I_Unit). (unit : !T_unit) -> (I_unit : !T_I_unit) ->
    (P : %unroll Unit I_Unit unit I_unit -> Type) -> !Unit -> Type;
!T_unit ===
  %self(unit). (I_unit : !T_I_unit) -> %unroll Unit I_Unit unit I_unit;
!T_I_unit ===
  %self(I_unit). (P : %unroll Unit I_Unit unit I_unit -> Type) ->
    %unroll I_Unit unit I_unit P (%unroll unit I_unit) ->
    %unroll I_Unit unit I_unit P !unit;
!unit ===
  %fix(u). (P : %unroll Unit I_Unit unit I_unit -> Type) =>
    (x : P (%unroll unit I_unit)) => %unroll I_unit P x;

fix%Unit (I_Unit : !T_I_Unit) (unit : !T_unit) (I_unit : !T_I_unit) : Type = !Unit;
I_Unit : !T_I_Unit = %fix(I_Unit). unit => I_unit => P => %expand P;

fix%unit (I_unit : !T_I_unit) : !Unit = !unit;
I_unit : !T_I_unit = %fix(I_unit). P => %expand P;

Unit = %unroll Unit I_Unit unit I_unit;



FalseT = %self(False).
  (I_False : %self(I_False).
    (P : %unroll False I_False -> Type) ->
    (%self(f). (P : %unroll False I_False -> Type) -> I_False P f) -> Type)
   -> Type;
fix%False (I_False : ) =
  %self(f). (P : %unroll False I_False -> Type) -> I_False P f;
%self(u). (P : %unroll Unit I_Unit unit I_unit -> Type) -> P (%unroll unit I_unit) -> P u


fix%Unit (unit : T_unit) (I_unit : T_I_unit) =
  %self(u). (P : T unit I_unit -> Type) ->
    P (%unroll unit I_unit) -> P u;

fix%unit I1 : %self(u). (P : T unit I1 -> Type) -> P (%unroll unit I1) -> P u =
    %fix(u). (P : T unit I1 -> Type) => (x : P (%unroll unit I1)) => I1 P x;

expected : (P : _ -> Type) -> P (%unroll unit I1) -> P u
received : (P : _ -> Type) -> P (%unroll unit I1) -> P (%fix(u). (P : _ -> Type) => (x : P (%unroll unit)) => I1 P x)
unit =
(self%I : (f : %self(f). (P : %unroll False I -> Type) -> P (I f)) -> %unroll False I) =>
  %self(f). (P : %unroll False I -> Type) -> P (I f)

Γ, x : %self(x). T |- T : Type
------------------------------
%self(x). T : Type

Γ, x : %self(x). T |- M : T[x := %fix(x) : T. M]
------------------------------------------------
%fix(x) : T. M : %self(x). T

Γ |- M : %self(x). T
---------------------
%unroll M : T[x := M]

Γ |- N : P (%unroll (%fix(x) : T. M))
---------------------------------------
%expand(N) : P (M[x := %fix(x) : T. M])

----------------
%expand(N) === N


!Unit ===
  %self(u). (P : %unroll Unit I_Unit unit I_unit -> Type) ->
    %unroll I_Unit unit I_unit P (%unroll unit I_unit) ->
    %unroll I_Unit unit I_unit P u;
!T_I_Unit ===
  %self(I_Unit). (unit : !T_unit) -> (I_unit : !T_I_unit) ->
    (P : %unroll Unit I_Unit unit I_unit -> Type) -> !Unit -> Type;
!T_unit ===
  %self(unit). (I_unit : !T_I_unit) -> !Unit;
!T_I_unit ===
  %self(I_unit). (P : %unroll Unit I_Unit unit I_unit -> Type) ->
    %unroll I_Unit unit I_unit P (%unroll unit I_unit) ->
    %unroll I_Unit unit I_unit P !unit;
!unit ===
  %fix(u). (P : %unroll Unit I_Unit unit I_unit -> Type) =>
    (x : P (%unroll unit I_unit)) => %unroll I_unit P x;

fix%Unit (I_Unit : !T_I_Unit) (unit : !T_unit) (I_unit : !T_I_unit) : Type = !Unit;
I_Unit : !T_I_Unit = %fix(I_Unit). unit => I_unit => P => %expand P;

fix%unit (I_unit : !T_I_unit) : !Unit = !unit;
I_unit : !T_I_unit = %fix(I_unit). P => %expand P;



!Unit =
  %self(u). (P : %unroll Unit I_Unit I_unit -> Type) ->
    %unroll I_Unit I_unit P !unit ->
    %unroll I_Unit I_unit P u;
!unit =
  %fix(unit). (P : %unroll Unit I_Unit I_unit -> Type) =>
    (x : %unroll I_Unit I_unit P unit) => x;
!T_I_unit ===
  %self(I_unit). (P : %unroll Unit I_Unit I_unit -> Type) ->
    %unroll I_Unit I_unit P (%unroll unit I_unit) ->
    %unroll I_Unit I_unit P !unit;
!T_I_Unit =
  %self(I_Unit). (I_unit : !T_I_unit) ->
    (P : %unroll Unit I_Unit I_unit -> Type) -> !Unit -> Type;

fix%Unit I_Unit I_unit =
  %self(u). (P : %unroll Unit I_Unit I_unit -> Type) ->
    %unroll I_Unit I_unit P !unit ->
    %unroll I_Unit I_unit P u;;


!Unit =
  %self(u). (P : %unroll Unit I_Unit unit -> Type) ->
    P (%unroll unit) -> %unroll I_Unit unit P u
!T_unit = %self(unit). %unroll Unit I_Unit unit;
!T_I_Unit =
  %self(I_Unit). (unit : !T_unit) ->
    (P : %unroll Unit I_Unit unit -> Type) -> !Unit -> Type;


fix%Unit I_Unit unit = !Unit;
fix%I_Unit (unit : !T_unit) = P => P;

fix%unit : !T_unit =
  %fix()

fix%I_Unit unit
!Unit =
  %self(u). (P : %unroll Unit I_Unit -> Type) ->
    %unroll I_Unit P !unit -> %unroll I_Unit P u;
!unit =
  %fix(unit). (P : %unroll Unit I_Unit -> Type) =>
    (x : %unroll I_Unit P unit) => x;
!T_I_Unit =
  %self(I_Unit). (P : %unroll Unit I_Unit -> Type) -> !Unit -> Type
!T_Unit =
  %self(Unit). (I_Unit : !T_I_Unit) -> Type;

Unit = %unroll Unit I_Unit unit I_unit;


!Unit =
  %self(u). (P : %unroll Unit I_Unit -> Type) ->
    %unroll I_Unit P !unit -> %unroll I_Unit P u;
!unit =
  %fix(unit). (P : %unroll Unit I_Unit -> Type) =>
    (x : %unroll I_Unit P unit) => x;
!T_I_Unit =
  %self(I_Unit). (P : %unroll Unit I_Unit -> Type) -> !Unit -> Type
!T_Unit =
  %self(Unit). (I_Unit : !T_I_Unit) -> Type;

Unit I_Unit u = (
  fix%unit I_unit = %fix(unit). I_unit =>
    %fix(u). (P : %unroll Unit I_Unit -> Type) ->
      (x : %unroll I_Unit P (%unroll unit)) => %unroll I_unit P x;
  %self(u). (P : %unroll Unit I_Unit -> Type) ->
    %unroll I_Unit P unit -> %unroll I_Unit P u
);

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
fix%Bool = %self(b). (P : Bool -> Type) -> P true -> P false -> P b;
ind (b : Bool) = %unroll b;

fold : (b : Bool) -> (A : Type) -> A -> A -> A;
Bool = (A : Type) -> A -> A -> A;
fold (b : Bool) = b;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;

fold : (n : Nat) -> (A : Type) -> A -> (A -> A) -> A;
Nat = (A : Type) -> A -> (A -> A) -> A;
zero : Nat = A => z => s => z;
succ (n : Nat) : Nat = A => z => s => s (n A z s);




received: (I_Unit : (I_UnitT : (Unit : UnitT : Type) -> Type) (Unit : UnitT : Type)) -> Type
expected: (I_Unit : (I_UnitT : Type) (Unit : UnitT : Type)) -> Type

fix%Eq A x y = (
  refl A x : Eq A x x = %fix(eq). P => x => x;
  // use equality to ensure that y is equal to x inside of P
  %self(eq). (P : (y : A) -> Eq A x y -> Type) -> P x (refl A x) -> P y eq
);
refl A x : Eq A x x = %fix(eq). P => x => x;

uip_refl_on A x (eq : Eq A x x) =
  (P : Eq A x x -> Type) => (x : P eq) =>
    %unroll eq (y => eq => P (eq (y => Eq A y x) (refl A y)));

Eq _ eq (eq (y => Eq A x y) (refl A x))

Eq _ (refl A x) ((refl A x) (y => Eq A x y) (refl A x))
Eq _ (refl A x) (refl A x)

a A a === b A b
%self(refl). (A : Type) -> (x : A) ->
  %self(eq). (P : Eq A x x -> A -> Type) -> P (refl A x) x -> P eq x
fix%refl A x
  : %self(eq). (P : Eq A x x -> Type) -> P (refl A x) -> P eq =
  %fix(eq). (P : Eq A x x -> Type) => P () -> P eq;


fix%False (I_False) =
  %self(f). (P : %unroll False I_False) -> P (%unroll I_False Id f);


%self(I). Eq _ (%unroll T I) (%unroll B refl T I);


!Unit =
  %self(u). %unroll Unit0 unit0 I_unit u;
!Unit0 =
  (P : (u : !Unit) -> Type) -> P (%unroll unit0 I_unit) -> P u;
!unit0 =
  %fix(u : !Unit0). (P : (u : !Unit0) -> Type) =>
    (x : P (%unroll unit0 I_unit)) => %unroll I_unit P x;

!T_I_unit =
  %self(I_unit). (P : (u : !Unit0) -> Type) ->
    P (%unroll unit0 I_unit) -> P !unit0
!T_unit0 =
  %self(unit0). (I_unit : !T_I_unit) -> !Unit0;
!T_unit0 =
  %self(unit0). (I_unit : !T_I_unit) -> !Unit0;
!T_Unit0 =
  %self(Unit0). (unit0 : !T_unit0) -> (I_unit : !T_I_unit) ->
    (u : !Unit) -> Type;

fix%Unit0 unit0 I_unit (u : !Unit) = !Unit;
fix%unit0 I_unit = !unit0;
fix%I_unit = P => P;

Unit = %self(u). %unroll Unit0 unit0 I_unit u;
unit : Unit = %unroll unit0;


Unit : Type;
unit : Unit;

Unit = %self(u). (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;



!Unit0 =
  u @-> (P : Unit -> Type) -> (x : P (@IT unit)) -> P (@IT u);
!T_IT =
  IT @-> !Unit0 -> Unit;

!unit0 = (u : !Unit0) @=> (P : Unit -> Type) => (x : P unit) => @I1 P x;
!T_I1 = I1 @-> (P : Unit -> Type) -> (x : P unit) -> P (!unit0);

Unit0 (Unit : Type) (IT : !T_IT) (unit : Unit) = !Unit0;
unit0 (Unit : Type) (unit : Unit) (I1 : !T_I1) = !unit0;


!Unit =
  u @-> @Unit0 IT unit I1;
!Unit0 =
  u @-> (P : !Unit -> Type) ->
    (x : @IT unit I1 P (@unit I1)) -> @IT unit I1 P u;
!IT
!unit0 =
  (u : !Unit0) @=> (P : !Unit -> Type) =>
    (x : @IT unit I1 P (@unit I1)) => @I1 P x;
!I1

!T_I1 =
  I1 @-> (P : !Unit -> Type) -> (x : P (@IT unit)) -> P (!unit0)
!T_unit =
  unit @-> (I1 : !T_I1) -> !Unit0;
!T_IT =
  IT @-> (unit : !T_unit) -> (I1 : !T_I1) -> (u : !Unit0) -> !Unit;
!T_Unit0 =
  Unit0 @-> ()
!T_Unit = Type;

Unit =
  Unit @=> (IT : !T_IT)
    (unit : unit @-> (I1 : !T_I1) -> Unit IT unit I1) (I1 : !T_I1)
  = Unit0 (Unit IT unit I1) IT (IT (@unit I1));

IT = _;
fix%unit (I1 : !T_I1) = unit0 (Unit IT unit I1) unit I1;


%self(I1). (P : Unit -> Type) -> P unit ->
  P (IT )
%fix(u). (P : Unit -> Type) => (x : P unit) =>

fix%False IT =
  %self(f). (P : %unroll False IT -> Type) -> %unroll IT P f;

%fix. _A =>
  %self. (%unroll \2 \1 -> Type) -> %unroll \2 \0 \1;

_A := %self. _B
%unroll \2 : _B[\0 := \2]

expected : (%unroll \1 \0 -> Type) -> _C
received : _B[\0 := \2]
%unroll \2 \0 :

IT : %self. (%unroll \1 \0 -> Type) ->
IT : _A

_A := %self(x). _B


(A : Type\0) => (x : A\0) => (x\0 : A\1)

%unroll IT :_B[x := IT]


(P : %unroll False IT -> Type) -> _C `unify` _B[x := IT]

_B := (P : %unroll False x -> Type) -> _C;
_C :=
  (%self(f). (P : %unroll False x -> Type) -> %unroll x P f) -> Type
((P : %unroll False IT -> Type) -> _C)[x := IT]

M : _A
%unroll M : _A[]

fix%False IT =
  %self(f). (P : %unroll False IT -> Type) -> %unroll IT P f;

%fix(False). (IT : _A) =>
  %self(f). (P : %unroll False IT -> Type) -> %unroll IT P f


(%unroll IT) (P : %unroll False IT -> Type) f

fix%False (IT : _A) =
  %self(f). (P : %unroll False IT -> Type) -> %unroll IT P f;

IT : _A
%unroll IT : _B[x := IT]
_A := %self(x). _B
%unroll IT P : _C[x := IT]
_B := (P : %unroll False x -> Type) -> _C
%unroll IT P f : Type
_C := (%self(f). (P : %unroll False x -> Type) -> %unroll x P f) -> Type;


fix%False (IT : _A)=
  %self(f). (P : %unroll False\2 IT\1 -> Type) -> %unroll IT\2 P\0 f\1;


IT\2 : _A[+2]

%unroll IT\2 : _B[IT\2][-2]
_A : %self(x). _B[+1]
%unroll IT\2 P\0 : _C[IT\2][-2]
_B := ((P : %unroll False\2 IT\1 -> Type) -> _C)[IT\2][-2]
%unroll IT\2 P\0 f\1 : Type
_C := ((%self(f). (P : %unroll False\2 IT\1 -> Type) -> %unroll IT\2 P\0 f\1) -> Type)

fix%Unit IT unit I1 =
  %self(u). (P : %unroll Unit IT unit I1 -> Type) ->
    %unroll IT unit I1 (%unroll unit I1) -> %unroll IT unit I1 u;

Unit = %unroll Unit (%fix(IT). P => x => %expand x);
fix%unit I1 : %unroll Unit unit I1 = P => x => %unroll I1 P x;

Unit = Unit unit (%fix(I1). P => x => %expand x);
unit : Unit = unit _;

fix%Bool IT true I1 false I2 = (
  IT = %unroll IT true I1 false I2;
  Bool = %unroll Bool IT true I1 false I2;
  true = %unroll true I1 false I2;
  false = %unroll false I2;

  %self(b). (P : Bool -> Type) -> IT P true -> IT P false -> IT P b
);

fix%Unit IT unit I1 =
  %self(u). (P : %unroll Unit IT unit I1 -> Type) ->
    P (%unroll IT unit I1 (%unroll unit I1)) ->
    P (%unroll IT unit I1 u);

f = (x : _A) => (P : x) -> %unroll x\1 x\1

_A := %self(y). _B
%unroll x\1 : _B[-1][x\1]

fix%False (IT : _A)=
  %self(f). (P : %unroll False\2 IT\1 -> Type) -> %unroll IT\2 P\0 f\1;


%unroll (IT\2 : _A[2]) : _B[-2][IT\2]
_A[2] `unify` %self(x). _B
_A := %self(x). _B[-2]



fix%False (IT : _A)=
  %self(f). (P : %unroll False\1 IT\2 -> Type) -> %unroll IT\2 P\4 f\3;

%unroll IT\2 : _B
_A := %self(x). _B

%unroll IT\2 P : _C
_B := (P : %unroll False\1 IT\2 -> Type) -> _C

%unroll IT\2 P\4 f\3 : Type
_C := (%self(f). (P : %unroll False\1 IT\2 -> Type) -> %unroll IT\2 P\4 f\3) -> Type;

%self(x). (P : %unroll False\1 IT\2 -> Type) -> (%self(f). (P : %unroll False\1 IT\2 -> Type) -> %unroll IT\2 P\4 f\3) -> Type

(x : _A) => (f : _B) => f\0 x\1

f\0 : _C -> _D
_B := (_C -> _D)[0]
x\1 : _C
_C := _A[1]
f\0 : _A[1] -> _D

!Unit =
  %self
fix%Unit IT

!False = %self(f). (P : %unroll False IT -> Type) -> %unroll IT P f;
!IT_T = %self(IT). (P : %unroll False IT -> Type) -> !False -> Type;
fix%False (IT : !IT_T) = !False;


!Unit =
  %self(u). (P : %unroll Unit IT unit I1 -> Type) ->
    %unroll IT unit I1 P (%unroll unit I1) -> %unroll IT unit I1 P u;
!unit =
  %fix(u). (P : %unroll Unit IT unit I1 -> Type) =>
    %unroll I1 P ((x : %unroll IT unit I1 (%unroll unit I1)) => x);
!T_IT =
  %self(IT). (P : %unroll Unit IT unit I1 -> Type) -> !Unit -> Type;
!T_I1 =
  %self(I1). Eq _ (%unroll unit I1) !unit;
fix%Unit (IT : !T_IT) (unit : !T_unit) (I1 : !T_I1) = !Unit;


fix%Unit IT = (
  fix%unit
    (I1 : %self(I1). (P : %unroll Unit IT -> Type) -> %unroll IT P (%unroll unit I1) -> %unroll IT P u)
    = %fix(u)
      : (P : %unroll Unit IT -> Type) -> %unroll IT P (%unroll unit I1) -> %unroll IT P u
      . (P : %unroll Unit IT -> Type) => %unroll I1 P ((x : %unroll IT P u) => x);

  %self(u). (P : %unroll Unit IT -> Type) ->  %unroll IT P unit -> %unroll IT P u
);



!unit =
  %fix(u)
    : (P : %unroll Unit IT -> Type) ->
      (x : %unroll IT P (%unroll unit I1)) => %unroll IT P u
    . (P : %unroll Unit IT -> Type) =>
    (x : %unroll IT P (%unroll unit I1)) => %unroll I1 P x;
!Unit =
  %self(u). (P : %unroll Unit IT -> Type) ->
    %unroll IT P (%unroll unit I1) -> %unroll IT P u;
!T_IT =
  %self(IT). (P : %unroll Unit IT -> Type) -> !Unit -> Type;
!T_I1 =
  %self(I1). (P : %unroll Unit IT -> Type) ->
    %unroll IT P (%unroll unit I1) -> %unroll IT P !unit;
!T_unit =
  %self(unit). (I1 : !T_I1) -> !Unit;
fix%Unit (IT : !T_IT) = (
  unit = %fix(unit : !T_unit). (I1 : !T_I1) => !unit;
  I1 = %fix(I1 : !T_I1). (P : %unroll Unit IT -> Type) =>
    (x : %unroll IT P (%unroll unit I1)) => %expand x;
  !Unit
);


!Unit = %self(u). %unroll Unit0 T_I1 unit0 I1 u;
!unit = %unroll unit0 I1;

!Unit0 =
  (P : !Unit -> Type) -> P !unit -> P u;
!T_unit0 =
  %self(unit0). (I1 : T_I1) -> !Unit;
!T_Unit0 =
  %self(Unit0). (T_I1 : Type) -> (unit0 : !T_unit0) ->
    (I1 : T_I1) -> (u : !Unit) -> Type;

!unit0 =
  %fix(u) : !Unit0. (P : !Unit -> Type) => (x : P !unit) =>   %unroll I1 P x;
!T_I1 =
  %self(I1). (P : !Unit -> Type) -> P !unit -> P !unit0;


cast : (%self(u). !Unit0) -> !Unit;

fix%Unit0 T_I1 unit I1 u = !Unit0;


fix%unit0 I1

fix%unit I1 = %fix(u) : %unroll Unit unit I1 u.
  (P : (self%u : %unroll Unit unit u) -> Type) =>
    (x : P (%unroll unit I1)) => %unroll I1 P x;
fix%unit = %unroll unit0


!Unit = %unroll Unit0 FT T_F1 unit0 F1;
!unit = %unroll unit0 F1;
!FT = %unroll FT T_F1 unit0 F1;

!Unit0 =
  %self(u). (P : !Unit -> Type) ->
    !FT P !unit -> !FT P u;
!unit0 = %fix(u : !Unit0).
  (P : !Unit -> Type) => (x : !FT P !unit) =>

!T_FT =
  %self(FT). (T_F1 : Type) -> (unit0 : !T_unit0) -> (F1 : T_F1) ->
    (P : !Unit -> Type) -> !Unit0 -> Type;
!T_unit0 =
  %self(unit0). (F1 : T_F1) -> !Unit0;
!T_Unit0 =
  %self(Unit0). (FT : !T_FT) -> (T_F1 : Type) ->
    (unit0 : !T_unit0) -> (F1 : T_F1) -> Type;

!T_F1 =
  %self(F1). (x : !FT P !unit) -> !FT P !unit0


fix%Unit0 FT T_F1 unit0 F1 = !Unit0;


%self(False, f). (P : False -> Type) -> P f

%self(Unit, u).

UnitT =
  %self(A, Unit).
    (Eq_A : Eq _ A A) =>
    (Eq_Unit : Eq _ Unit (

    )) =>
    _;

%fix(A, Unit). (Eq_A : Eq _ A UnitT) =>
  (Eq_Unit : Eq _ Unit)


Γ, A : Type, x : A |- T : Type
------------------------------
%self(A, x). T : Type

Γ, A : Type, x : A |- T
-----------------------
%self(A, x). T : Type


%self(A, Unit). (unit : A) -> Type;

%fix(A, Unit). W => unit =>
  %self(u). (P : Unit W -> Type) -> W P unit -> W P u;

Γ, x : T |- T : Type
------------------------------
%self(x). T : Type

%self(Unit, T).
  (eq : %exists(X). Eq _ U Type) ->
  Type;

%self(False). (eq : %self(eq). Eq _ (False eq) _) -> Type

%fix(False). (eq : %self(eq). Eq _ _ (False eq)) =>
  %self(f). (P : False eq -> Type) -> P (%unroll eq (X => X) f)

%self(False). (f : %self(f). %unroll False f) -> Type;


%fix(U, Unit). (unit : %self) =>
  (P : Unit -> Type) -> P u;

Unit W1 W2 = %self(Unit, u). (P : Unit -> Type) -> W1 Unit P u -> W2 Unit P u;

%self(A, x). (P : A -> Type) -> P x;

%unroll (%fix(A, x). A);

%self(A, x). A


fix%False W0 = (
  False = %unroll False W0;
  W0 = %unroll W0;
  %self(f). (P : False -> Type) -> W0 P f;
);



Unit : Type;
unit : Unit;

Unit = %self(u). (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;

// expanded
fix%Unit unit W0 W1 = (
  Unit = %unroll Unit unit W0 W1;
  unit = %unroll unit W0 W1;
  W0 = %unroll W0 W1;
  %self(u). (P : Unit -> Type) -> W0 P unit -> W0 P u;
);
fix%unit W0 W1 : %unroll Unit unit W0 W1 = (
  Unit = %unroll Unit unit W0 W1;
  unit = %unroll unit W0 W1;
  W0 = %unroll W0 W1;
  W1 = %unroll W1;
  %fix(u). (P : Unit -> Type) => (x : W0 P unit) => W1 P x;
);

Unit = %unroll Unit unit (%fix(W0). P => P) (%fix(W1). P => P);
unit : Unit = %unroll unit _ _;




fix%Bool true false W0 W1 W2 = (
  Bool = %unroll Bool true false W0 W1 W2;
  true = %unroll true false W0 W1 W2;
  false = %unroll false W0 W1 W2;
  W0 = %unroll W0 W1 W2;
  %self(b). (P : Bool -> Type) -> W0 P true -> W0 P false -> W0 P b;
);
fix%unit W0 W1 : %unroll Unit unit W0 W1 = (
  Unit = %unroll Unit unit W0 W1;
  unit = %unroll unit W0 W1;
  W0 = %unroll W0 W1;
  W1 = %unroll W1;
  %fix(u). (P : Unit -> Type) => (x : W0 P unit) => W1 P x;
);

//
fix%False (W0 : _A) =
  %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;

_A := %self(x). _B
%unroll W0 : _B[x := W0]

_A :=
%unroll W0\2 : _B[x := W0\2]

_A := %self(x). _B

(A : Type\1) -> A\2



fix%False (W0 : %self(W0).
  (P : %unroll False\1 W0\2 -> Type) ->
  (f : %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\5 f\4) ->
  %unroll False\1 W0\2
) =
  %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;


fix%False (W0 : _A) =
  %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;

W0\2 : _A[+2]

_A := %self(x). _B[-2]
%unroll W0\2 : _B[W0\2]

_B := (P : %unroll False\1 W0\2 -> Type) -> _C
%unroll W0\2 P\4 : _C[P\4]

_C := (f : %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\5 f\4) -> Type

%unroll W0\2 P\4 f\3 : Type


%self(x). (P : %unroll False\1 W0\2 -> Type) -> _C[-2]

f => value => f value;


(value : (value : _B))

(value : _B) -> ?


(_A x)[x := 2]
((x => ) y)

fix%Bool true false W0 W1 W2 = (
  Bool = %unroll Bool true false W0 W1 W2;
  true = %unroll true false W0 W1 W2;
  false = %unroll false W0 W1 W2;
  W0 = %unroll W0 W1 W2;
  W1 = %unroll W1 W2;
  W2 = %unroll W2;
  %self(b). (P : Bool -> Type) -> W0 P true -> W0 P false -> W0 P b;
);
fix%true false W0 W1 W2 = (
  Bool = %unroll Bool true false W0 W1 W2;
  true = %unroll true false W0 W1 W2;
  false = %unroll false W0 W1 W2;
  W0 = %unroll W0 W1 W2;
  W1 = %unroll W1 W2;
  W2 = %unroll W2;
  %fix(b). (P : Bool -> Type) => (x : W0 P true) => (y : W0 P false) => W1 P x;
);
fix%false W0 W1 W2 = (
  Bool = %unroll Bool true false W0 W1 W2;
  true = %unroll true false W0 W1 W2;
  false = %unroll false W0 W1 W2;
  W0 = %unroll W0 W1 W2;
  W1 = %unroll W1 W2;
  W2 = %unroll W2;
  %fix(b). (P : Bool -> Type) => (x : W0 P true) => (y : W0 P false) => W2 P y;
);

Bool : Type = %unroll Bool true false (%fix(W0). P => %expand P)
  (%fix(W1). P => %expand P) (%fix(W2). P => %expand P);
true : Bool = %unroll true false _ _ _;
false : Bool = %unroll true false _ _ _;

Bool : Type;
true : Bool;
false : Bool;

Bool = %self(b : Bool). (P : Bool -> Type) -> P true -> P false -> P b;
true = (P : Bool -> Type) => (x : P true) => (y : P false) => x;
false = (P : Bool -> Type) => (x : P true) => (y : P false) => y;


fix%False\1 W0\2 =
  %self(f\3). (P\4 : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;

W0\2 : _A[+2]

_A := (%self(x\2). _B)[-2]
%unroll W0\2 : _B[x\2 := W0\2]

_B := (P\4 : %unroll False\1 W0\2 -> Type) -> _C
%unroll W0\2 P\4 : _C[x\2 := W0\2]

_C := (f : %self(f\3). (P\4 : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3) -> Type;
%unroll W0\2 P\4 f\3 : Type


fix%False\1 (W0\2 : _A) =
  %self(f\3). (P\4 : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;

W0\2 : _A[-2]

_A := (%self(x). _B)[+2]
%unroll W0\2 : _B[x := W0\2]

(x : _A) => (y : _B) => x;

x : _A[+1]

_A := ((A : Type) -> A\2)[-1];

(x : _A) => (y : _B) => x


fix%False\1 (W0\2 : _A) =
  %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;

W0\2 : _A[+2]
_A := (%self(x). _B)[-2]
%unroll W0\2 : _B[x := W0\2]

P\4 : %unroll False\1 W0\2 -> Type
_B := (P : %unroll False\1 W0\2 -> Type) -> _C
%unroll W0\2 P\4 : _C[x := W0\2]

f\3 : %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\6 f\5
_C := (f : %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\6 f\5) -> Type;
%unroll W0\2 P\4 f\3 : Type


fix%False\1 (W0\2 :
  %self(W0\2). (P\3 : %unroll False\1 W0\2 -> Type) ->
    (f\4 : %self(f\2). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\5 f\4) -> Type
) =
  %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;

fix%False\1 (W0\2 : _A) =
  %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;

W0\2 : _A[+2]

_A := (%self(x). _B[+1])[-2]
%unroll W0\2 : _B[x := W0\2]

P\4 : %unroll False\1 W0\2 -> Type

_B := (P : %unroll False\1 W0\2 -> Type) -> _C[+1]
%unroll W0\2 P\4 : _C[x := W0\2]

f\3 : %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\5 f\4
_C := (f : %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\5 f\4) -> Type

%self(W0).
  (P : %unroll False\1 W0\2 -> Type) ->
  (f : %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\5 f\4) -> Type

fix%False (W0 : _A) =
  %self(f). (P : %unroll False\2 W0\1 -> Type) -> %unroll W0\2 P\0 f\1;

W0 : _A[+2]

_A := (%self(x). _B[+1])[-2]
%unroll W0\2 : _A[x := W0\2]

_B := (P : %unroll False\2 W0\1 -> Type) -> _C[+1]
%unroll W0\2 P\0 : _C[x := W0\2]

f\1 : %self(f). (P : %unroll False\3 W0\2 -> Type) -> %unroll W0\3 P\0 f\1
_C := (f : %self(f). (P : %unroll False\3 W0\2 -> Type) -> %unroll W0\3 P\0 f\1) -> Type

%self(W0). (P : %unroll False\3 W0\2 -> Type) -> (f : %self(f). (P : %unroll False\5 W0\4 -> Type) -> %unroll W0\5 P\0 f\1) -> Type


fix%False\1 (W0\2 : _A) =
  %self(f). (P : %unroll False\1 W0\2 -> Type) -> %unroll W0\2 P\4 f\3;


ind :
  %self(ind). (u : Unit) ->
    (P : Unit -> (P unit -> P u (%unroll ind u P)) -> Type) ->
    P unit (%unroll ind u) -> P u (%unroll ind u P);

%unroll u P (x : P unit) === x

match u with
| I => x
end ===


forall (A : Type) (x : A) (P : forall a : A, eq_t A x a -> Set),
       P x (eq_refl A x) -> forall (a : A) (e : eq_t A x a), P a e

eq_ind :
  (A : Type) -> (x : A) -> (y : A) -> (eq : Eq a x y) ->
  (P : (y : A) -> Eq A x y -> Type) ->
  P x (refl A x) -> P y eq
Eq A x y =
  %self(eq).
    (P : (y : A) -> Eq A x y -> Type) ->
      P x (refl A x) -> P y eq;


Eq : (A : Type) -> (x : A) -> (y : A) -> Type;
refl : (A : Type) -> (x : A) -> Eq A x x -> Type;

Eq A x y = %self(eq).
  (P : (y : A) -> Eq A x y -> Type) ->
  P x (refl A x) -> P y eq



Key : Type;
Frozen : {
  @Frozen : (A : Type, k : Key) -> Type;
  freeze : {A} -> (k : Key, x : A) -> Frozen(A, k);
  unfreeze : {A} -> (k : Key, x : Frozen(A, k)) -> A;
};

Nat_TE = ($Nat_key) => {
  // Nat.te
  @Nat = Frozen($Nat_key, Int);
  zero = Frozen.freeze($Nat_key, Int.zero);
  one = Frozen.freeze($Nat_key, Int.one);
  add = (n, m) => {
    n = Frozen.unfreeze($Nat_key, n);
    m = Frozen.unfreeze($Nat_key, m);
    Int.add(n, m)
  };
}
Nat_TEI = {
  // Nat.tei
  @Nat : Type;
  zero : @Nat;
  one : @Nat;
  add : (n : @Nat, m : @Nat) ->
};
M_TE = ($Nat_key, $M_key) => {
  Nat : Nat_TEI = Nat_TE($Nat_key);
  // M.te
  // this will fail
  one : Int = Nat.one;
};


(x : Frozen key Nat) =>
  unfreeze key


Unit : Type;
unit : Unit;

Unit = %self(u). (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;


fix%Unit I unit = (
  Unit = %unroll Unit I unit;
  I = %unroll I unit;
  unit = %unroll unit;
  %self(u). (P : Unit -> Type) -> P unit -> I P u;
);

fix%unit I = (
  unit = %unroll unit I;
  Unit = %unroll Unit unit;

)


%self(u). (P : Unit -> Type) -> P (I unit) -> P (I u)

T_u : Type;
unit : T_u;

T_u = %self(u). (P : Unit -> Type) -> P (I unit) -> P (I u);
unit = P => (x : P (I unit)) => x;

fix%Unit C = (
  Unit = %unroll Unit C;
  C = %unroll C;

  fix%unit C0 = (
    unit = %unroll unit C0;
    C0 = %unrol C0;

    %fix(u) :
      (P : Unit -> Type) -> P (C (C0 unit)) => x
      .
      (P : Unit -> Type) => (x : P (C (C0 unit))) => x
  );
  unit = %unroll unit _;

  %self(u). (P : Unit -> Type) -> P (C unit) -> P (C u)
);

Unit : %self(Unit). (u : %self(u). %unroll Unit u) -> Type;
unit : %self(u). %unroll Unit u;

Unit u = (P : (u : %self(u). %unroll Unit u) -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;

!Unit = %fix(Unit). K => u => (
  Unit = %self(u). %unroll Unit K u;
  K = %unroll K u;
  (P : Unit -> Type) -> P (K unit) -> P u
);
fix%UnitK unit = (
  Unit = !Unit;

);



%unroll Unit C u ->

Unit : Type;
unit : Unit;

Unit = %self(u). (P : %unroll Unit -> Type) -> P unit -> P u;
unit = (P : %unroll Unit -> Type) => (x : P unit) => x;

!unit =
  %fix(u): (P : Unit -> Type) -> P (C (%unroll unit C0)) -> P (C u).
    (P : Unit -> Type) => (x : P (C (%unroll unit C0))) => %unroll C0 P x;

!T_C0 =
  %self(C0). (P : Unit -> Type) -> P (C (%unroll unit C0)) -> P (C (!unit));

fix%Unit C = (
  Unit = %unroll Unit C;
  C = %unroll C;

  fix%unit (C0 : !T_C0) = !unit;
  C0 : !T_C0 = %fix(C0). P => P;

  unit = ;

  %self(u). (P : %unroll Unit C -> Type) ->
    P (C (%unroll unit ?)) -> P (C u);
);


received :
  %unroll I P (%fix(unit). P => (x : %unroll I P unit) => x) -> %unroll I P (%fix(unit). P => (x : %unroll I P unit) => x)


fix%unit I = (
  (P : Unit -> Type) => (x : P unit) =>
)


Unit Unit C unit C0 = (
  Unit = %unroll Unit C unit C0;
  C = %unroll C unit C0;
  unit = %unroll unit C0;
  C0 = %unroll C0;

  %self(u). (P : Unit -> Type) -> P unit -> C P u
);
unit Unit C unit C0 = (
  Unit = %unroll Unit C unit C0;
  C = %unroll C unit C0;
  unit = %unroll unit C0;
  C0 = %unroll C0;

  %fix(u). (P : Unit -> Type) => (x : P unit) => C0 P x;
);

fix%Unit C unit C0 = (
  ;
);
fix%unit =


Unit : (u : %self(u). %unroll Unit u) -> Type;
unit : %unroll Unit unit

Unit u = (P : (u : %self(u). %unroll Unit u) -> Type) -> P unit -> P u;
unit = (P : (u : %self(u). %unroll Unit u) -> Type) => (x : P unit) => x;


Bool0 = {
  self%Bool : (self%b : %unroll Bool b) -> Type;
  self%true : %unroll Bool true;
  self%false : %unroll Bool false;

  Bool b = (P : (self%b : Bool b) -> Type) ->
    P true -> P false -> P b;
  true = P => x => y => x;
  false = P => x => y => y;
};

Bool = %self(b). %unroll Bool0.Bool b;
true : Bool = Bool0.true0;
false : Bool = Bool0.false0;





Mutual
  (T_T : Type)
  (M_T_T : (T : T_T) -> Type)
  (T_C0 : (T : T_T) -> Type)
  (M_T_C0 : (T : T_T) -> (C0 : T_C0 T) -> Type)
  (E_T : %self(E_T).
    (T : %self(T). (C0 : T_C0 T) -> M_T_T (%unroll E_T T C0)) ->
    (C0 : T_C0 T) -> T_T)
  (E_C0 : %self(E_C0). (T : T_T) ->
    (C0 : %self(C0). M_T_C0 T (%unroll E_C0 T C0)) -> T_C0 T)
  (M_T : (T : T_T) -> (C0 : T_C0 T) -> M_T_T T)
  (M_C0 : (T : T_T) -> (C0 : T_C0 T) -> M_T_C0 T C0)
  (T : T_T, C0 : T_C0 T) = (
  fix%T (C0 : T_C0 T) : M_T_T (%unroll E_T T C0) = M_T (%unroll E_T T C0);
  fix%C0 : M_T_C0 (%unroll E_C0 T C0) = M_C0 T (%unroll E_C0 T C0);
  (%unroll E_T T C0, %unroll E_C0 T C0);
);


// from
Unit : (u : %self(u). %unroll Unit u) -> Type;
unit : %unroll Unit unit

Unit u = (P : (u : %self(u). %unroll Unit u) -> Type) -> P unit -> P u;
unit = (P : (u : %self(u). %unroll Unit u) -> Type) => (x : P unit) => x;

// to
(Unit, unit) = Mutual
  // types
  (%self(Unit). (u : %self(u). %unroll Unit u) -> Type)
  (Unit => (u : %self(u). %unroll Unit u) -> Type)
  (Unit => %self(unit). %unroll Unit unit)
  (Unit => unit => %unroll Unit unit)
  // equalities
  (%fix(E_Unit). Unit => unit => Unit)
  (%fix(E_unit). Unit => unit => unit)
  // values
  (Unit => unit => u =>
    (P : (u : %self(u). %unroll Unit u) -> Type) -> P unit -> P u)
  (Unit => unit =>
    (P : (u : %self(u). %unroll Unit u) -> Type) => (x : P unit) => x);



// (fst : %self(fst). (s : %self(s). (K : Type) -> (A -> B (%unroll fst s) -> K) -> K) -> A)

fix%fst0 (A : Type) (B : A -> Type)
  (s : %self(s). (K : Type) -> (A -> B (%unroll fst0 A s) -> K) -> K) =
  %unroll s A ((x : A) => (y : B (%unroll fst0 A s)) => x);

Pair (A : Type) (B : A -> Type) =
  %self(s). (K : Type) -> (A -> B (%unroll fst0 A s) -> K) -> K;
pair (A : Type) (B : A -> Type) (x : A) (y : B x) : Pair0 A B =
  %fix(s). (K : Type) => (k : A -> B x -> K) => k x y;
fst (A : Type) (B : A -> Type) (s : Pair A B) =
  %unroll fst0 A s;
snd (A : Type) (B : A -> Type) (s : Pair A B) =
  %unroll s (B (fst A B s)) ((x : A) => (y : B (fst A B s)) => y);

self%Unit : Type;
unit : Unit;

Unit = %self(u). (P : (u : %self(u). %unroll Unit u) -> Type) -> P unit -> P u;
unit = (P : (u : %self(u). %unroll Unit u) -> Type) => (x : P unit) => x;

!MUnit = %unroll MUnit MI;

!Unit = fst Type (Unit => Unit) !MUnit;
!unit = snd Type (Unit => Unit) !MUnit;

!Unit0 = %self(u). (P : !Unit -> Type) -> P (!unit) -> T P u;
!unit0 = %fix(u). (P : !Unit -> Type) => (x : P (!unit)) => C0 P x;

!T_T = %self(T). (P : !Unit -> Type) -> (u : !Unit0) -> Type;

!T_C0 = %self(C0). (P : !Unit -> Type) -> P (!unit) -> T P (!unit0);
!T_MI = Pair (!T_T) ((T : !T_T) => !T_C0);
!T_MUnit = %self(MUnit). (MI : !T_MI) -> Pair Type (Unit => Unit);

fix%MUnit (MI : !T_MI) =
  pair Type (Unit => Unit) (!Unit0) (!unit0);

MI = %fix(MI).
Eq (A : Type) (x : A) (y : A) =
  (P : A -> Type) -> P x -> P y;

Bool =
  %self(k). (K : Type) ->
    ( -> K) -> K -> K;

case (b : ?) (K : Type) (x : ?) (y : ?) =
  %unroll b K x y;

T =%self(eq). (K : Type) -> (x : _) -> (y : _) -> Eq _ (case b K x y) (x eq);
case b Int ((eq : ) => 0) (() => 1)


;

  (Unit => unit => %unroll Unit unit)

  (Unit => unit => u => (P : (u : %self(u). %unroll Unit u) -> Type) -> P unit -> P u)
  (Unit => unit => (P : (u : %self(u). %unroll Unit u) -> Type) => (x : P unit) => x);
T_False : Type;
T_C : (False : T_False) -> Type;

T_False =


T_False =
  %self(False).
    (C : %self(C). (f : %self(f). (P : %unroll False C -> Type) -> P (%unroll C f)) -> %unroll False C)
  -> Type;
T_C (False : T_False) =
  %self(C). (f : %self(f). (P : %unroll False C -> Type) -> P (%unroll C f)) -> %unroll False C;

fix%False (C : %self(C). (f : %self(f). (P : %unroll False C -> Type) -> P (%unroll C f)) -> %unroll False C) =
  %self(f). (P : %unroll False C -> Type) -> P (%unroll C f);

Bool = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;

Bool = %frozen key Bool;
true : Bool = %freeze key true;
false : Bool = %freeze key false;



fix%fst0 (A : Type) (B : A -> Type)
  (s : %self(s). (K : Type) -> (A -> B (%unroll fst0 A s) -> K) -> K) =
  %unroll s A ((x : A) => (y : B (%unroll fst0 A s)) => x);

Pair (A : Type) (B : A -> Type) =
  %self(s). (K : Type) -> (A -> B (%unroll fst0 A s) -> K) -> K;
pair (A : Type) (B : A -> Type) (x : A) (y : B x) : Pair0 A B =
  %fix(s). (K : Type) => (k : A -> B x -> K) => k x y;
fst (A : Type) (B : A -> Type) (s : Pair A B) =
  %unroll fst0 A s;
snd (A : Type) (B : A -> Type) (s : Pair A B) =
  %unroll s (B (fst A B s)) ((x : A) => (y : B (fst A B s)) => y);


%self(fst0).
  (A : Type) -> (B : A -> Type) ->
  (s : %self(s). (K : Type) -> (A -> B (%unroll fst0 A s) -> K) -> K) ->
  A;

fix%fst0 (A : Type) (B : A -> Type)
  (s : %self(s). (K : Type) -> (A -> B (%unroll fst0 A s) -> K) -> K) =
  %unroll s A ((x : A) => (y : B (%unroll fst0 A s)) => x);

%self(fst0).
  (A : Type) -> (B : A -> Type) ->
  (s : %self(s). (K : Type) -> (A -> B (%unroll fst0 A s) -> K) -> K) ->
  A;


%self(False). (f : %self(f). %unroll False f) -> Type;

False : %self(x). _A;

// enter arrow
_A := (f : _C) -> _D;
// enter param
f : %self(f). _B
_C := %self(f). _B;

%unroll False : (f : %self(f). _B[x := False]) -> _D[x := False];
_B := %unroll False _E


%unroll False f : Type

%self(f). %unroll False _E[x := False] `unify` %self(f). %unroll False f

_D[x := False] `unify` %self(f). %unroll False f
_B := %self(f). %unroll False f;
// leave f

_A := %self(x).


%self. (%self. %unroll \1 \0) -> Type;
%self. (%self. %unroll (\1 : _A) (\0 : _B)) -> Type;

_A := %self. _C
%self. (%self. (%unroll \1 : _C) \0) -> Type;

_C[\1] `unify` (_D -> Type);
_B := _C[\1]
%self. (%self. %unroll \1 \0) -> Type

_B := %self. %unroll \1 \0;


%self(False0). (f : %self(f0). %unroll False0 f0) -> Type;


False0 : %self(False1). _A[False0 := False1]

// enter arrow
_A := (f : _C) -> _D;

// enter %self(f0)
f0 : %self(f1). _E
_C := %self(f0). _F


%unroll False0 : (f : %self(f0). _F[False1 := False0]) -> _D[False1 := False0]

_A[False1 := False0] `unify`
(f : %self(f). %unroll False f) -> Type



%self(False0). (f : %self(f0). %unroll False0 f0) -> Type;

False0 : %self(False1). _A[False0 := False1]
f0 : %self(f1). _B[f0 := f1]

%unroll False0 : _A[False0 := False1][False1 := False0]

_A[False0 := False1][False1 := False0] `unify` (f : _C) -> _D
_A :=
%unroll False0 f


%self(False0). (f : %self(f0). %unroll False0 f0) -> Type;

// enter self False
False0 : %self(False1). _A[False0 := False1]

// enter arrow
_A := (f : _B) -> _C

// enter self f
_B := %self(f0). _D
f0 : %self(f1). _D[f0 := f1]

// enter apply
_D := _F _G;

// enter unroll
_F := %unroll False0;
%unroll False0 : _A[False0 := False1][False1 := False0]


(f : %self(f0). %unroll False0 f0) -> _C[False0 := False1][False1 := False0]
// enter f0
_G := f0


_C[False0 := False1][False1 := False0] `unify` Type

expected

received : %self(f1). _E[f0 := f1]
expected : %self(f0). unroll False0 _F[False0 := False1][False1 := False0]



%self(False). (f : %self(f). %unroll False f) -> Type;

False : %self(False). _A
f : %self(f). _B

_A := %self(x).
%unroll False : _A


_A[x := y] === _A


call = f => x => (f : _A -> _B) x

id : (A : Type) -> A -> A;

x = call{Type, ?}(id, A);


%self(False0). (f : %self(f0). %unroll False0 f0) -> Type;

False0 : %self(False1). _A[False0 := False1]

%unroll False0 : _A[False1 := False0]


_A := (f : %self(f0). %unroll False0 f0) -> Type


f : (x : _A) -> _B
f y : _B y

(f y : Int)

%self(False0). (f : %self(f0). %unroll False0 f0) -> Type;

False0 : %self(False1). _A[False0 := False1]
f0 : %self(f1). _B[f0 := f1]

%unroll False0 : _A[False0 := False1][False1 := False0]
%unroll False0 : _A

_A := (f : _C) -> Type
_C := %self(f1). _B[f0 := f1];
%unroll False0 f0 : Type
// leave f0

(f : %self(f1). %unroll False0 f1) -> Type
`unify`
(f : %self(f0). %unroll False0 f0) -> Type


%self(False). (%self(f). %unroll False\1 f\0) -> Type;

// enter False
False : _A

// enter f
f : _B

(False\1 : _A[+1])

_A := %self(False). _C
%unroll False\1 : _C[+1]

_C := (_B[-1]) -> Type;
%unroll False\1 f\0 : Type;

_B := %self(f). %unroll False\2 f\0
// leave f

%self(False). (%self(f). %unroll False\1 f\0) -> Type `unify`
%self(False). (%self(f). %unroll False\1 f\0) -> Type

List : {
  @List : (A : Type) -> Type;
  map : {A, B} -> (f : A -> B, l : List A) -> List B;
} = _;

Mappable = {
  @Container : Type;
  map : {A, B} -> (f : A -> B, l : Container A) -> Container B;
};

map {M : Mappable} (x, f) = M.map(f, x);

User : (User : Type) & Map [
  ("id", User -> Nat)
  ("name", User -> String)
] = {
  id : Nat;
  name : String;
};

User = Record [
  ("id", Nat);
  ("name", String);
];

eduardo = Record.make User [
  ("id", 0);
  ("name", "Eduardo");
];
Map.get("id", eduardo)


User : {
  id : User -> Nat;
  name : User -> String;
};

user.id;
User.id(user)
l.map(x => )


l_ = List.map(f, l);
l.map(f);

map{List}(f, l);
l.map{List}(f);

x = List.map(f, l);
x = 1;







User : {
  id : Nat;
  name : String;
};

User = Record [
  ("id", Nat);
  ("name", String);
];
eduardo = User [
  ("id", 0);
  ("name", "Eduardo");
];

"id"

_Int\0 -> _Int\0
(A : Type) => A\0


(A : Type) => _A

%self(False0). (f0 : %self(f0). %unroll False0 f0) -> Type;

False0 : %self(False1). _A[False0 := False1]
f0 : %self(f1). _B[f0 := f1]

%unroll False0 : _A

_A := (f0 : _B) -> Type


%self(f1). _B[f0 := f1] `unify` %self(f0). %unroll False0 f0

_B[f0 := f1][f1 := f2] `unify` (%unroll False0 f0)[f0 := f2]

%self(False0). (f0 : %self(f0). %unroll False0 f0) -> Type;

False0


%self(False0/1). (f0 : %self(f0/2). %unroll False0/1 f0/2) -> Type;

False0 : %self(False1/1). _A
f0 : %self(f1/2). _B

False0/1 : (%self(False1/1). _A)[+2]
%unroll False0/1 : _A[+1]

f0/2
_A := (f0 : (%self(f1/2). _B)[-1]) -> Type

(A : Type) -> 'A -> 'A

Int/+2 -> Int/+2

(A : Type) -> A/-1 -> A/-2



(A : Type) -> (A/+3 -> A/+3)[close 3]

(A : Type) -> (A/+3 -> A/+3)[close 3]

%self(False0/1). (f0 : %self(f0/2). %unroll False0/1 f0/2) -> Type;

False0/+1 : %self(False1). _A[False0/+1 := False1/-1]
f0/+2 : %self(f1). _B[f0/+2 := f1/-1]

%unroll False0/+1 : _A[False0/+1 := False1/-1][False1/-1 := False0/+1]

%self(False0/1). (f0 : %self(f0/2). %unroll False0/1 f0/2) -> Type;

False0/+1 : %self(False1). _A[close +1]
f0/+2 : %self(f1). _B[close +2]

%unroll False0/+1 : _A[close +1][open +1]

_A := (f0 : %self(f1). _B[close +2]) -> Type;
%unroll False0/+1 f0/+2 : Type

_B := %unroll False0/+1 f0/+2

%self(False0). (f0 : %self(f0). %unroll False0/-2 f0/-1) -> Type;

False0 : %self(False1). _A[close +1]
f0 : %self(f1). _B[close +2]

_A := (f0 : %self(f1). _B[close +2]) -> Type;

%self(f1). _B[close +2] `unify` %self(f0). %unroll False0/-2 f0/-1
_B[close +2] `unify` %unroll False0/-2 f0/-1
_B `unify` %unroll False0/-2 f0/-1

_B := (%unroll False0/-2 f0/-1)[open +2]
_B := %unroll False0/-2 f0/+2

%self(False0). (f0 : %self(f0). %unroll False0/-2 f0/-1) -> Type;

False0 : _A
f0 : _B

_A := %self(False1). _C
%unroll False0/+1 : _C

_C := (f0 : _B) -> Type
%unroll False0/+1 f0/+2

_B := %self(f0). %unroll False0/+1 f0/-1

%self(False1). %self(f0). %unroll False0/+1 f0/-1

%self(False0). (f0 : %self(f0). %unroll False0/-2 f0/-1) -> Type;

False0 : _A
f0 : _B

_A := %self(False1). _C
%unroll False0/-2 : _C[False0/-2]

_C := (f0 : _B) -> Type
_B := %self(f0). %unroll False0/-2 f0/-1

%self(False1). (f0 : %self(f0). %unroll False0/-2 f0/-1) -> Type


%self. (%self. %unroll /1 /0) -> Type;

/1 : _A
/
%self. (%self. %unroll /1 /0) -> Type;

/1 : _A[+1]
/0 : _B

_A := %self. _C[-1]
%unroll /1 : _C[/1]

_C := (f0 : _B) -> Type
_B := %self. %unroll /1 /0

%self. (f0 : %self. %unroll /1 /0) -> Type

A\

%self(False0). (f0 : %self(f0). %unroll False0/-2 f0/-1) -> Type;
False0 : %self. _A
f0 : %self. _B

%self(False0). (f0 : %self(f0). %unroll False0 f0) -> Type

False0 : %self(False1). _A
f0 : %self(f1). _B

%unroll False0 : _A[False1 := False0]

Option A =
  (tag : Bool, tag | true => A | false => Unit);

Option A =
  | (tag : "some", A)
  | (tag : "none");

(f : Option Int) =>
  switch (f) {
  | ("some", x) => x + 1
  | ("none") => 0
  };
(f : Option Int) =>
  match f
  | ("some", x) => x + 1
  | ("none") => 0;

(f : Option Int) =>
  match f with
  (("some", x) => x + 1)
  (("none") => 0)
  end;

(f : Option Int) =>
  f
  | ("some", x) => x + 1
  | ("none") => 0


Bool = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;

accepts_string_or_nat
  : (pred : Bool) -> (x : pred Type String Nat) -> pred Type String Nat
  = (pred : Bool) => (x : pred Type String Nat) => x;

accepts_string
  : (x : String) -> String
  = accepts_string_or_nat true;


Option A =
  | (tag : true, payload : A)
  | (tag : false);

OptionX A =
  | (tag : false)
  | (tag : true, payload : A);

Option A =
  (tag : Bool, payload : tag | true => A | false => Unit);


((A : Type) => (x : A) => x) Int : Int -> Int

f : (A : Type) -> A -> A
Int : Type


f : (A : _A) -> _B


(A : Type)

(A/+2)[close +2 to -1] -> A/+2[close +2 to -2]

[], [] |- _A[close +2 to -1] `unify` _B[open -1 to +2]
[close +2 to -1], [open -1 to +2] |- _A `unify` _B

_A := _B

Int `unify` String

_A `unify` (A : Type) -> A -> A

%self(False0). (f0 : %self(f0). %unroll False0 f0) -> Type;

False0/+2 : %self(False1). _A[close False0/+2]
f0/+3 : %self(f1). _B[close f0/+3]

%unroll False0/+2 : _A[close False0/+2][open False0/+2]

_A[close False0/+2][open False0/+2] `unify`
(f0 : %self(f1). _B[close f0/+3]) -> Type


%self(False0). (f0 : %self(f0). %unroll False0 f0) -> Type;
False0 : %self(False1). _A[False0 := False1]
f0 : %self(f1). _B[f0 := f1]

%unroll False0 : _A

_A := (f0 : %self(f1). _B[f0 := f1]) -> Type;
%unroll False0 f0 : Type

_B := %unroll False0 f0

_A{x := y} `unify` _A{y := 1}

%self(False0). (f0 : %self(f0). %unroll False0 f0) -> Type;
False0/2 : %self(False1). _A/2[False0/2 := False1/-1]
f0/3 : %self(f1). _B[f0/3 := f1/-1]


_C/4 := (x : _A/2) -> _B/3

(x : _A) -> _B[+2 `close` -1] `unify` (A : Type) -> A/-1 -> A/-2

_A := Type

_B[+2 `close` -1] `unify` A/-1 -> A/-2

_B{+2 `close` -1} `unify` A/-1 -> A/-2

_B := (A/-1 -> A/-2)[-1 `open` +2]

(x : _A) -> _B


(x : _A) -> _B `unify` (A : Type) -> A/-1 -> A/-2


_B[x := y] `unify` Int
_B := Int

_B y
_B := _ => Int

_B[A := Int] `unify` _B[A := String]


(x : _A) -> _B[-1 `open` +2] `unify` (A : Type) -> A/-1 -> A/-2

_B := A/-1 -> A/-2

%self(False0). (f0 : %self(f0). %unroll False0 f0) -> Type;

False0/+2 : %self(False1). _A[/+2 `close` /-1]
f0/+3 : %self(f0). _B[/+3 `close` /-1]

%unroll False0/+2 : _A[/+2 `close` /-1][/-1 := False0/+2]

_A := (f0 : %self(f0). _B[/+3 `close` /-1]) -> Type
%unroll False0/+2 f0/+3

_B := %unroll False0/+2 f0/+3

%self(False1). (f0 : %self(f0). %unroll False0/-2 f0/-1) -> Type



#self[x => x]
@self[]

@deriving(show)
User = {
  id : Nat;
};

@rec(User) = {

};

@self(x -> x)
@fix(x => x)
@unroll(M)
@unroll()
@unfold()

%fix(False). %self(f). (P : False -> Type) -> P f;


%self(False0). (f0 : %self(f0). %unroll False0 f0) -> Type;

False0/+2 : %self(False1). _A[/+2 `close` /-1]
f0/+3 : %self(f0). _B[/+3 `close` /-1]

%unroll False0/+2 : _A[/+2 `close` /-1][/-1 := False0/+2]

_A := (f0 : %self(f0). _B[/+3 `close` /-1]) -> Type
%unroll False0/+2 f0/+3

_B := %unroll False0/+2 f0/+3

Nat : {
  @Nat : Type;
} = {
  @Nat = Int;
};

Alias : Type = (x : Int) -> Int;

JSON : {
  ... : Type;
} = _;

Nat : {
  T : Type;
} = {
  T = Int;
};


(x : Nat) =>

JSON =
  | Null
  | Bool(b : Bool)
  | Number(n : Float64)
  | String(s : String)
  | Object(d : List(String, @JSON))
  | Array(l : List(@JSON));
JSON = JSON & {

};

User : (User : Type) & {
  id : (user : User) -> Nat;
  name : (user : User) -> String;
} = {
  id : Nat;
  name : String;
};

x = User.id(user);

(x : fst T).k === (snd T).k;

(x : T).k === T::k(x);

User : (User : Type) & fst {
  id : Nat;

} = {
  id : Nat;
  name : String;
};

eduardo = { id = 0; name = "Eduardo"; };
x = eduardo::name;
User::id(user);


(x : T).k === T::k(x);

User : (User : Type) & {
  id : (user : User) -> Nat;
  name : (user : User) -> Nat;
} = (User = {
  id : Nat;
  name : String;
}) & {
  id = (user : User) => user::id;
  name = (user : User) => user::name;
};


Show = {
  T : Type;
  show : (x : S) -> String;
};
show{S : Show}(x : S.T) = S.show()
// User.tei
User = {
  @User = {
    id : Nat;
    name : String;
  };
  impl@Show{self} = {
    show () =
      self.name ++ ": " ++ self.id.show();
  };
};

User = {
  ... = extend({
    id : Nat;
    name : String;
  });
}
... = include(Show);

(User = {
  id : Nat;
  name : String;
}) & {
  show({self}) =
    self.name ++ ": " ++ self.id.show();
};

User : (User : Type) & ((user : {
  id : Nat;
  name : String;
}) -> User) & {

}
eduardo = User {
  id = 0;
  name = "Eduardo";
};
print(eduardo.show());


(user : User).id === User::id(user);

(user : fst {
  id : Nat;
}).id === snd {
  id : Nat;
}.id(user)
(snd {
  id : Nat;
} : fst {
  id : (user : fst {
    id : Nat;
  }) -> Nat;
}).id === snd {
  id : (user : fst {
    id : Nat;
  }) ->
}.id(User);

JSON : Type & {

} = {
  ... @JSON =
    | Null
    | Bool(b : Bool)
    | Number(n : Float64)
    | String(s : String)
    | Object(d : List(String, @JSON))
    | Array(l : List(@JSON));
};

@self(JSON, _). (
  JSON : Type,
)
( == ) = (
  ( == ) = (P : ) &
  ( == ) =
)
f = x => x;

add = (a, b) => a + b;
f(1, 2)

deprecate : {A} ->


external : (key : String, A : Type) -[Const]> A;

hello = external("teika_c_hello", () -> String);


User = {
  id : Nat;
  name : String;
};

Row : {
  type : (row : Row) -> Type;
} = _;
Record : {
  Record = List(Row);
  type : (record : Record) -> Type;

  make : (rows : List(row : Row, value : Row.type row)) ->
    Record.type(List.map(fst, rows));

  keyof : (A : Type) -[Error]>
} = _;

keyof(User)


T_fst0 = %self(fst0).
  (A : Type) -> (B : Type -> Type) ->
  (s : %self(s). (K : Type) -> (A -> B (%unroll fst0 A B s) -> K) -> Type) -> A;
fst0 = %fix(fst0 : T_fst0).
  A => B => s => %unroll s A (x => y => x);

Sigma (A : Type) (B : Type -> Type) =
  %self(s). (K : Type) -> (A -> B (%unroll fst0 A B s) -> K) -> Type;
fst (A : Type) (B : Type -> Type) (s : Sigma A B) : A =
  %unroll fst0 A B s;
snd (A : Type) (B : Type -> Type) (s : Sigma A B) : B (fst A B s) =
  %unroll s (B (fst A B s)) (x => y => y);

// CPSify

// from
(snd e : B (fst e))
// to
{K} => (k : B (fst e) -> K) =>
  e (y => snd y k)

T_fst0 = %self(fst0). {A} -> {B} ->
  (s : %self(s). {K} -> (A -> B (%unroll fst0 s) -> K) -> K) ->
  {K} -> (A -> K) -> K;

fst0 : T_fst0 = %fix(fst0). {A} => {B} =>
  s => {K} => k => %unroll s (x => y => k x);

Sigma A B =
  %self(s). {K} -> (A -> B (%unroll fst0 s) -> K) -> K;
fst {A} {B} (s : Sigma A B) =
  %unroll fst0 s;
snd {A} {B} (s : Sigma A B) {K} (k : B (fst s) -> K) =
  %unroll s K (x => y => k y);



E_T :

((x : {K} -> (Int -> K) -> K) -> x == 1)
(x = 1, eq : x == 1 = eq_refl)


(k : B (fst A B e)) => e ((s : Sigma A B) -> k (snd s))


// from
(e : Sigma A B)

// to
e : %fix(T). %self(e). {K : T -> Type} ->
  (k : (y : Sigma A B) -> K (%fix(w). {K} => (k : (y : _) -> K w) => k y)) ->
  K e

CPSify Sigma

CPSifying Sigma seems to suffer from the same issue as lambda encoding of any inductive type, which is self reference.

The lambda encodings of inductive types can be solved by using self types, instead of declaring unit using the traditional church encoding, by using self types we self encode the induction principle, allowing to be known that (u : Unit) -> u == unit.

// traditional church encoding of unit, no induction
Unit : Type;
unit : Unit;

Unit = (A : Type) -> (x : A) -> A;
unit = A => x => x;

// self dependent encoding of unit, inductive
Unit : Type;
unit : Unit;

Unit = %self(u). (P : Unit -> Type) -> P unit -> P u;
unit = P => x => x;

Instead of doing the traditional polymorphic CPS version, we can do a self referential CPS version

// original
x : A;
x = e;

// traditional CPS polymorphic
CPS : (A : Type) -> Type;
CPS = A => (K : Type) -> (k : (x : A) -> Type) -> K;

x : CPS A;
x = K => k => k e;

// self referential version
CPS : (A : Type) -> Type;
CPS = A => %self(x). (K : CPS A -> Type) ->
  (k : (y : T) -> K (K => k => k y)) -> K x;

x : CPS A;
x = K => k => k e;

This allows to transform any external callback.

example : B (fst x)
example = x (a => B (fst a)) (y => snd y);

Algebra

f(x) = x + 1;

f(2);
2 + 1


n = m

1 + n = 1 + m


n - 1 = m - 1

1 + x = 2
x = 2 - 1

(1 + x) - 1 = (2) - 1
x = 2 - 1

Back to Teika

sort effects to achieve a set

extensions should be environment scoped, as in open should import extensions

@simpl, @cbn, @cbv, with a simple heuristics when the type is huge

expansion heuristics based on grading both for type level and term level

maybe type of dependent let should be a let
then, should type of a dependent apply be an apply?


() -> IO (Result String Error);
() -> Result (IO String) Error;

() -[IO | Error]> String;
() -[Error | IO]> String;

() -> Eff [IO, Error] String;
() -> Eff [Error, IO] String;

Eff effects ret = (
  effects = Set.of_list(Effect => Effect.name, effects);
  RawEff effects ret;
)
() -> Eff [IO, Error] String;
() -> Eff [Error, IO] String;


fold : (b : Bool) -> (A : Type) -> A -> A -> A;
// internalizing works
Bool = (A : Type) -> A -> A -> A;

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
// internalizing fails, unbounded b, plus requires mutual recursion
Bool = (P : Bool -> Type) -> P true -> P false -> P b;

// with self the following can be done
Bool : Type;
true : Bool;
false : Bool;

Bool = %self(b). (P : Bool -> Type) -> P true -> P false -> P b;
true = P => x => y => x;
false = P => x => y => y;


(x : _A) -> _B `unify` (x : Int) -> P x\-0


(A : Type) => (x : A\-1) => (x : A\-2)
(x : A\+1) => (x : A\+1)

(x = 3; id (x + 1))
id (x + 1)

(A = Int; (1 : Int))

() -> Option(String);

IO(Option(String));
Option(IO(String));

Effect = (l, r) => (
  l = sort(l);
  Raw(l, r)
);

expected : () -> Eff([IO; Option], String);
received : () -> Eff([Option; IO], String);

read : () -[IO]> String;
f = () => read();

({
  T = Int;
  x : T = 1;
} :> {
  x : Int
}) === {
  x : Int = 1;
}

({
  T = Int;
  x : T = 1;
} :> {
  x : Int
})


Int0 = _;
x0 : Int0;

Int = @frozen(((A : Type) => A) Int0);
x0 : Int = @freeze(x0);

Unit0 = _;
unit0 = _;

Unit = @frozen(Unit0);
unit = @freeze(unit0);
ind_unit = (u : Unit) => @unroll(@unfreeze(u));


Eq {A} x y : Type;
refl {A} x : Eq x x;

Eq {A} x y =
  @self(eq ->
    (P : (z : A) -> Eq x z -> Type) ->
    P x (refl x) -> P y eq
  );
refl {A} x = other => P => (x : P other x (refl x)) =>
  other (refl x) (eq => _ => _ => P eq x (refl x)) x;


(x : Eq a b) => (p : P a) =>
  x (refl a)
expected : P other x (refl x) -> P (refl x) x (refl x)
received : P other x (refl x) -> P (refl x) x (refl x)
uip : {A} -> (x : A) -> (eq : Eq x x) -> Eq eq (refl x)
  = {A} => x => eq =>
    eq (_ => eq0 => Eq eq0 (refl x)) (refl (refl x))

Eq (eq (z => _ => Eq z y) eq) (refl x)

f x = g x
f = g

f x = g x



f P f = g P g -> f = g;

!T_IT =
!T_unit = @self(unit -> @unroll Unit IT I0 unit);
!T_

T_Unit = @self(Unit ->
  T_unit = @self(unit -> (IT : _) -> (I0 : _) -> @unroll Unit unit IT I0);
  T_IT = (unit : T_unit) -> @self(IT -> (I0 : _) ->
    (P : _) -> (u : @self(u -> (P : _) -> P (@unroll unit IT I0) -> @unroll IT I0 P u)) -> _)
  (unit : @self(unit -> (IT : _) -> (I0 : _) -> @unroll Unit unit IT I0)) ->
  (IT : @self(IT -> (I0 : _) ->
    (P : _) -> (u : @self(u -> (P : _) ->
      P (@unroll unit IT I0) -> @unroll IT I0 P u)) -> _)) ->
  (I0 : @self(I0 ->
    (P : _) -> P unit -> P (@fix((u : Unit) => (P : Unit -> Type) => (x : P unit) => I0 P x)))) ->
  Type
);
Unit = @fix(Unit => unit => IT => I0 => (
  Unit = @unroll Unit unit IT I0;
  unit = @unroll unit IT I0;
  IT = @unroll IT I0;
  I0 = @unroll I0;


  @self(u -> (P : Unit -> Type) -> P unit -> IT P u);
));
unit = @fix(unit => IT => I0 => (
  Unit = @unroll Unit unit IT I0;
  unit = @unroll unit IT I0;
  IT = @unroll IT I0;
  I0 = @unroll I0;

  @fix((u : Unit) => (P : Unit -> Type) => (x : P unit) => I0 P x)
));

Unit = @unroll Unit;

Eq0 A x y = (P : A -> Type) -> P x -> P y;
Eq1 A x y


Nullable (A : Type) (not_nullable : Repr.not_nullable A) = A | null;
Nullable (Nullable A not_nullable) (?)

@mu(x -> )


add = (a, b) => a + b;

expr
| true => 1
| false => 2

Bool = | true | false;

add_and_mul = (a, b) => (
  c = a + b;
  a * c;
);

add_and_mul = (a, b) => (
  c = a + (
    d = b;
    b + 1
  );
  a * c
);

no logical system can be complete and consistent

Naive set theory
does the set of all sets contains themselves?

forall x : Nat, (y : Nat, y > x)

1 = 0

(x => x + 1)(1)
1 + 1
2

f : (x : Nat) -> Fix Nat;
f : (x : Nat) -> Nat;

sort = selection_sort;
is_a_sort : bubble_sort == selection_sort = _;

f = l => first(sort(l));
f = subst(sort, f, bubble_sort);


fix = f => f(f);

Int = @frozen(((A : Type) => A) Int0);
x0 : Int = @freeze(x0);

Unit0 = _;
unit0 = _;

Unit = @frozen(Unit0);
unit = @freeze(unit0);
ind_unit = (u : Unit) => @unroll(@unfreeze(u));

Γ, f : @f(x : A) -> B, x : A |- B : Type
---------------------------------------
Γ |- @f(x : A) -> B : Type

Γ, f : @f(x : A) -> B, x : A |- M : B[x := @f(x : A) => M]
----------------------------------------------------------
Γ |- @f(x : A) => M : Type

Γ |- M : @f(x : A) -> B   Γ |- N : A
-----------------------------------
Γ |- M N : B[f := M][x := N]

Id = @id(A : Type) -> (x : )
Rec () = Rec () -> Type;

(f(x : A) => M) N ===
M[f := f(x : A) => M][x := ]

Γ, f : @f(x : A) -> B, x : A |- B : Type
---------------------------------------
Γ |- @f(x : A) -> B : Type

False@0 : Type@0
T_False : Type@ω = @self(False@n -> (f : @self(f -> @unroll False@n f)) -> Type@n);
False : T_False = @fix(False@n => f =>
  (P : @self(f -> @unroll False@n f) -> Type) => P f);

T_False (n : Level) : Type@(n + 1) =
  @self(False@n -> (f : @self(f@n -> @unroll False@n f@n)) -> Type@n);

False : T_False =
  @fix(False@1 => f => (P : @self(f@0 -> @unroll False@1 f@0) -> Type) -> P f);


@fix(Fix@1 -> @unroll Fix@1 -> ())

@fix(Fix@1 -> @unroll (@fix(Fix@0 -> @unroll Fix@0 -> ())) -> ())

Γ |- M : @self(x@n+1 -> T)
---------------------------------
Γ |- @unroll M : T[x := @upper M]


----------------------------------------------------------------
@unroll (@fix(x@n+1 => M)) === M[x := @upper (@fix(x@n+1 => M))]


@unroll (@fix(Fix@0 -> @unroll Fix@0 -> ())) -> ()


@unroll (@fix(Fix@1 -> @unroll Fix@1 -> ()))


@unroll (@fix(False@1 => @self(f@0 -> (P : @unroll False@1 -> Type@0) -> P f@0)))


T_False (l : Level) : Type (l + 2) =
  @self(False@l -> (f : @self(f@l -> @unroll False f)) -> Type (l + 1))

False l : T_False l =
  @fix(False@l => f => (P : @self(f@l -> @unroll False f) -> Type l) -> P f);



False l : Type (l + 1) = @self(f@l -> @unroll (False l) f);


@fix(False@1 => f => (P : @self(f@1 -> @unroll False f) -> Type 1) -> P f)

f : @self@1(f@l -> @unroll (False l) f)
@lower f : @self@0(f@l -> @unroll (False l) f)

@unroll f : (P : @self(f@0 -> @unroll False f) -> Type 0) -> P (@lower f)

@unroll f

False 0

@unroll (@fix(False@1 => f => (P : @self(f@0 -> @unroll False f) -> Type 0) -> P f));


f : @unroll False 1
f : (P : @unroll False 0 -> Type) -> P (@lower f);

f : @unroll (@fix(False@1 => @self(f@1 -> (P : @unroll False@1 -> Type@1) -> P f@1)))

f : @self(f@1 -> (P : @unroll (@fix(False@0 => @self(f@0 -> (P : @unroll False@0 -> Type@1) -> P f@0))) -> Type@1) -> P f@1)

@unroll f : (P : @self(f@0 -> (P : @unroll False@0 -> Type@1) -> P f@0) -> Type@1) -> P (@lower f)

@self(f@0 -> (P : @unroll False@1 -> Type@0) -> P f@0)

False@1 : @self(False@0 -> Type@0)

Fix : Type@2 = @unroll (@fix(Fix@1 -> @unroll Fix@1 -> ()))

fix : Fix = (f : @unroll (@fix(Fix@2 -> @unroll Fix@2 -> ()))) => f(f);

fix(fix)
@unroll False@1 : (f : @self(f@0 -> @unroll False@1 f@0)) -> Type@0




Γ |- M : @self(x@n+1 -> T)
--------------------------
Γ |- @unroll M : T[x := M]


@Unit () => @u(P : Unit () -> Type) -> P unit -> P u;

@fix(Unit). @self(u). (P : @unroll Unit -> Type) -> @expand P unit -> @expand P u

expected : @self(u). (P : @unroll Unit -> Type) -> P unit -> P u
received : @self(u). (P : @unroll Unit -> Type) -> P unit -> P u

(tag, payload : tag | true => String | false => Int)
tag | true => (payload : String)


ind (u : Unit) = @unroll u;

ind u

Γ |- A : Type
---------------------
Γ |- @frozen A : Type

Γ |- M : A
--------------------------
Γ |- @freeze M : @frozen A

Γ |- M : @frozen A
--------------------
Γ |- @unfreeze M : A

---------------------------
@unfreeze (@frozen M) === M
Car = interface(Car => {
  speed : (self : Car) -> Speed;
  top_speed : (self : Car) -> Speed;

  speed_is_always_smaller_than_top_speed :
    (self : Car) -> self.speed() < self.top_speed();
});

Bug = class(implements(Car), self => {
  speed = 10;
  top_speed = 120;
  speed_is_always_smaller_than_top_speed = _;
});

Car = @fix(Car => @self(this -> {
  speed : Speed;
  top_speed : Speed;

  speed_is_always_smaller_than_top_speed :
    this.speed < this.top_speed;
}));

Bug : Car = @fix(this => {
  speed = 10;
  top_speed = 120;
  speed_is_always_smaller_than_top_speed = _;
});


Electric_car = (top_speed, battery) => {
  ...Car(top_speed);
  battery_size : () => baterry;
};

bug = Car(120);
bug.top_speed()
TEq : Type -> Type -> Type;
trefl : (A : Type) -> TEq A A;

TEq A B = @self(teq ->
  (P : (C : Type) -> TEq A C -> Type) ->
  P A (trefl A) -> P B teq;
);
trefl A = P => x => x;



HEq : {A, B} -> A -> B -> Type;
hrefl : {A} -> (x : A) -> HEq x x;

HEq {A, B} x y = @self(heq ->
  (K : Type -> Type) ->
  (P : (T : Type) -> (z : T) -> HEq x z -> K T) ->
  P A x (hrefl x) -> P B y heq
);
hrefl {A} x = P => x => x;

uip_heq {A} (x : A) (heq : HEq x x) : HEq heq (hrefl x) =
  heq (T => z => heq => HEq heq (hrefl x)) (hrefl x);

heq (T => a => HEq a 1) a

heq_to_eq {A} (x : A) (y : A) (heq : HEq x y) : Eq x y =
  heq (T => z => _ => (x : T) -> Eq x z)

Eq : {A} -> A -> A -> Type;
refl : {A} -> (x : A) -> Eq x x;

Eq {A} x y = @self(eq ->
  (P : (T : Type) -> T -> (z : A) -> Eq x z -> Type) ->
  P (Eq x x) (refl x) x (refl x) -> P (Eq x y) eq y eq
);
refl {A} x = P => x => x;

uip_equal {A} (x : A) (eq : Eq x x) : Eq eq (refl x)
  = @unroll eq (_ => _ => eq_e => Eq eq_e (refl x))
      (@unroll eq
        (z => eq => _ =>
          Eq (@unroll eq _ (refl x)) (refl x))
        (refl x))

Induction

Option (A : Type) =
  | Some (payload : A) : Option A
  | None : Option A;

Some : (A : Type) -> (payload : A) -> Option A;
None : (A : Type) -> Option A;

Ty (A : Type) =
  | Ty_string : Ty String
  | Ty_int : Ty Int;

One_or_zero (n : Nat) =
  | Zero : One_or_zero 0
  | One : One_or_zero 1;

f = (A : Type) => (ty : Ty A) => (x : A) : String =>
  ty
  | Ty_string => (x : String)
  | Ty_int => Int.to_string(x : Int);

id
  : (A : Type) -> (x : A) -> A
  = (A : Type) => (x : A) => x;

p : (x : Nat, x == 1)

fst p : Nat
snd p : (fst p) == 1

id = k => x => k x;

sum_3 = a => b => c => k => sum a b (a_b => sum a_b c k);
sum_3 = a => b => c => sum (sum a b) c;

Point : Type = sig
  val "x" Int
  val "y" Int
end;

zero_zero : Point = struct
  let "x" 0
  let "y" 0
end;

Point : Type = @sig({
  x : Int;
  y : Int;
});

Unit0 : @self(Unit0 -> _);
unit0 : @self(unit0 -> @unroll Unit0 unit0 _ _);

Unit1 = @unroll Unit0 unit0 _ _;
unit1 : Unit1 = unit0;

Unit = @frozen Unit1;
unit : Unit = @freeze unit1;

Unit : {
  @Unit : Type;
  unit : @Unit;

} = _;

Ind_type (T : Type) = (P : Type -> Type) -> P Type ->
    ((A : Type) -> (B : A -> Type) -> P ((x : A) -> B x)) -> P T;

Term (A : Type) =

Type : Type;

Type : @fix(Type => @self(T ->
  (P : Type -> Type) -> P Type ->
  P ((A : Type) -> (B : A -> Type) -> P ((x : A) -> B x)) -> P T
));

------
Type 0

---------------------
Type n : Type (n + 1)


Type : @fix(Type => @self(T -> (P : Type -> Type) -> P Type -> P T))



Type 1 : @self(T -> (P : Type 1 -> Type 1) -> P (Type 0) -> P T)

Type 1 : @unroll (Type 2) (X => )

----------------
Type 0 : Type 1

A : Type 0  B : Type 0
----------------------
(x : A)

Type 'n : Type ('n + 1);
(x : 'A : Type 'n) -> ('B x : Type 'n) : Type 'n;
(x : 'A) => (body : 'B x) : (x : 'A) -> 'B x;
(M : (x : 'A) -> 'B x) (N : 'A) : 'B N;

Type (n + 1) = @self(T -> (P : Type (n + 1) -> Type (n + 1)) ->
  P ((A : Type n) -> (B : Type n) -> P ((x : A) -> B x)) -> P T);
((x : 'A) -> 'B x) = P => forall => forall A B;
((x : 'A) => body) = (arg : 'A) => body[x := arg];
(lambda arg) = lambda arg;



Ind_lambda A B f = (P : ((x : A) -> B x) -> Type) ->
  ((x : A) -> (r : B x) -> P ((x : A) => R x)) -> P f;

Map_W A B w = (x : A) -> (y : A) -> (Iso x y) -> W x -> W y;
eq : (x : A) -> f x = g x;
w : W ((x : A) => f x);



fn = ((x : A) => f x);
ind fn (f => W f)
  (x => r => eq );

() -> IO (Option String);
() -> Option (IO String);

() -[Option | IO]> String;

Eff l = IEff (sort l) String;

() -> Eff [Option; IO] String;
() -> Eff [IO; Option] String;


List.map (x => external ("c_" ++ x)) ["hello"; "world"]

FFI = {
  hello : String = "hello";
};
[external "c_hello"; external "c_world"]


ind

Linear Computer

Machine

Nat64 : {
  dup : (src : &Nat64, to_ : &mut Nat64) -> ();
  // arith
  add : (a : &Nat64, b : &Nat64, to_ : &mut Nat64) -> ();
  sub : (a : &Nat64, b : &Nat64, to_ : &mut Nat64) -> ();
};
Mem : {
  // better API
  split : (mem : Mem, at : &Nat64) -[Invalid_offset]> (left : Mem, right : Mem);
  merge : (left : Mem, right : Mem) -[Invalid_right]> (mem : Mem);

  // TODO: is ptr needed?
  load : (mem : &Mem, ptr : &Nat64, dst : &mut Nat64) -> ();
  store : (mem : &mut Mem, ptr : &Nat64, src : &Nat64) -> ();
};

System

File : Type;
open : (
  mem : &Mem,
  path : &Nat64,
  flags : &Nat64,
  ret : Reg
) -> (file : File);
write : (
  file : &mut File,
  mem : &mut Mem,
  buf : &Nat64,
  len : &Nat64,
  ret : Reg
) -> Nat64;

Table : Type;
load : (table : &mut Table, fd : Nat64) -> (file : File);
store : (table : &mut Table, file : File) -> (fd : Nat64);

Linearity

F A = (G A, G A);

(x : Int) -> Eff([Fix], Int)

JavaScript

@fix((x) : Int => @unroll x);


type Ret<A> =
  // TODO: unbox this, typeof or instanceof
  | { tag : "jmp"; to_ : () => Ret<A>; }
  | { tag : "ret"; value : A; };
type Fn<A, B> = (x : A) => Ret<B>;

function $call (f) {
  const stack = [];
}

function $fix (f) {
  return f(() => $fix(f));
};

$call
$jmp
$fix(x => y => x());

k => x => y => k y

Beta

true = x => y => x;

(x => y => x)(1)
(y => x)[x := 1]
(y => 1)

([], x => y => x)


true(1) -> ([1], x => y => x)
true(1)(2) -> ([1; 2], x => y => x)

true(1) -> (1, true)
true(1)(2) -> (1, 2, true) -> 1

Bound Escape

received : _B/+2 -> (A : Type) -> A/-1
expected : _B/+2 -> (A : Type) -> _B/+2

A/+3 `unify` _B/+2


f = x => (y => y)(x);
g = x => x;

[],((λ (λ (λ ((#3 #2) s)))) (λ #1)) === [],((λ (λ (λ ((#3 #1) t)))) (λ #1))
[(λ #1)],(λ (λ ((#3 #2) s))) === [(λ #1)],(λ (λ ((#3 #1) t)))
[(λ #1),Abs],(λ ((#3 #2) s)) === [(λ #1),Abs],(λ ((#3 #1) t))
[(λ #1),Abs,Abs],((#3 #2) s) === [(λ #1),Abs,Abs],((#3 #1) t)
[(λ #1),Abs,Abs],(#2 s) === [(λ #1),Abs,Abs],(#1 t)

[Type],(A : Type) => (A/+1)[+1 := -1]
[Type],0,(B : Type) => (A : Type) => (A/+1)[+1 := -1]
  [Type;B],0,(A : Type) => (A/+1)[+1 := -1]
  [Type;B;A],0,(A/+1)[+1 := -1]
  [Type;B;A;-1],+2,A/+1

[Type;-1],A/+1 -> A/-1

(A : Type) => A/-1
_B => _C

[Type; ]

[], (x => x)(y => y)(z)
  [], (x => x)(y => y)
  [x := y => y], x
  [x := y => y], y => y
  [], y => y
  [], (y => y)(z)
[], y

(x => x)(y => y)(z)
(x[x := y => y])(z)
(y => y)(z)
(y[y := z])
z

T[x := y; y := z]
z
(x => x)(y => y)

(x => x(x))(z => z)

x(x)[x := z => z]
(x[x := z => z])(x[x := z => z])
(z => z)(z => z)

_A[x :=]
[z => z],\0(\0)

_A[x := y] `unify` y
_A `unify` y[y := x]
_A `unify` x

_A := x


x[x := y] `unify` y

[],_A[x := z] `unify` [],y[y := z]
[x := z],_A `unify` [y := z],y
_A := y[y := x][x := z]
_A := z


[Type],(A : Type) => (A/+1)[+1 := -1]
[Type],(B : Type) => (A : Type) => (A/+1)[+1 := /-1]
    [Type;B],(A : Type) => (A/+1)[+1 := -1]
    [Type;B;A],(A/+1)[+1 := -1]
    [Type;B;A;-1],+2,A/+1

(A : Type) => (((B : Type) => B/+3[+3 := -1]) => A/+2)[+2 := -1]
(A : Type) => (((B : Type) => B/+1[+1 := -1]) => A/+2)[+2 := -1]

[]


fold : (b : Bool) -> (A : Type) -> A -> A -> A;
Bool = (A : Type) -> A -> A -> A;

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
Bool = b @-> (P : Bool -> Type) -> P true -> P false -> P b;

@Unit (@I : unit @-> _)
  (@unit : (@C0 : _) -> @Unit I unit C0) (@C0 : _) : Type =
  u @-> (P : @Unit I unit C0 -> Type) -> P (@unit C0) -> @I unit C0 P u;
@I unit C0 P x = x;
@unit C0 : @Unit I unit C0 = u @=> P => x => x;
@C0 P x = x;

expected : u
received : u @=> P => x => @C0 P x

@Unit
  (@unit : u @-> (C0 : _) => @Unit unit C0 u) C0
  (@u : @Unit unit C0 u) : Type =
  (P : (@u : @Unit unit C0 u) -> Type) -> P (@unit C0) -> P u;

@unit C0 : @u -> @Unit unit C0 u =
  u @=> P => x => @C0 P x;

@Unit (@I : _) : Type =
  u @-> (P : @Unit I -> Type) ->
  P (@I u) -> P (@I (u @=> P => x => x));

expected : P (@I (u @=> P => x => x))
received : P (@I u)

@Unit (@unit : _) (@C0 : _) (@u : @Unit u) : Type =
  (P : (@u : @Unit unit C0 u) -> Type) ->
  P u -> P (@unit C0);

T_unit = @Unit
@unit C0 : u @-> @Unit unit C0 u
  = u @=> P => x => @C0
@Unit
  (@I : _)
  (@unit : (C0 : _) -> @Unit I unit C0)
  (@C0 : _)
: Type =
  u @-> (P : @Unit I unit C0 -> Type) ->
  P (@I u) -> P (@unit C0);
I = _;

expected : @I P (u @=> P => (x : @I P u) => x)
received : @I P u


I : (u @-> (P : @Unit I -> Type) ->
  @I P (u @=> P => x => x) -> @I P u)
@Unit (@I : _) : Type =
  u @-> (P : @Unit I -> Type) ->
  P (@I (u @=> P => x => x)) -> P (@I u);

@Unit (@I : _) : Type =
  u @-> (P : @Unit I -> Type) ->
  P (@I (u @=> P => x => x)) -> P (@I u);

(x : A) => x
(x : B) => x



@Bool (@I : _) : Type =
  b @-> (P : @Bool I -> Type) ->
  @I P (b @=> P => x => y => x) ->
  @I P (b @=> P => x => y => y) ->
  @I P b;

expected : P (@I (u @=> P => (x : P (@I u)) => x))
received : P (@I (u @=> P => (x : P (@I u)) => x))
@Unit
  (@I : (u : _) -> @Unit I u)
  (@u : @Unit I u)
: Type = (P : (@u : @Unit I u) -> Type) ->
  P unit ->
  P u;

expected : @I P (u @=> P => (x : @I P u) => x)
received : @I P u

Γ, x : x @-> T |- M : T
----------------------- // fix
Γ |- (@x : T) @=> M : T


|>
.

f . g
\x -> f (g x)

x => f(g(x))


add_incr = (x) => (
  x = 1;
  incr = y => x + y;

  x = x + 3;
  incr(1)
);

id = (x : _A) => (x : _A);
id = {A} => (x : A) => (x : A)


generic = var.level > 1e6
generic = var.level < level

id = (x : _A\1) => (x : _A\1);

id : (x : 'A\1) => (x : 'A\1)

id : (x : _B\0) => (x : _B\0)
y = id 1;
z = id "a";

id = (x : _A\1) => (x : _A\1);

id : (x : _B\0) -> _B\0
id 1
id "a"


id = (A : Type) => (x : A) => x;

x = id _ 1;


console.log{Int}(123);


@Unit (@I :
  _
) : Type =
  u @->
    (P : @Unit I -> Type) ->
    P (@I ((@u : ) @=> P => x => x)) ->
    P (@I u);


expected : P (@I (u @=> P => x => x)) -> P (@I (u @=> P => x => x))
received : P (@I (u @=> P => x => x)) -> P (@I (u @=> P => x => x))
x => x : P (@I u) -> P (@I u)

Γ, x : x @-> T |- T : Type
-------------------------- // self
Γ |- x @-> T : Type





Γ, x : x @-> T |- M : T
----------------------------- // fix
Γ |- (@x : T) @=> M : x @-> T

x @=> (x : T)
x @-> T


Γ, x : x @-> T |- T : Type
-------------------------- // self
Γ |- x @-> T : Type

Γ, False : Self |-

Γ |- M : x @-> T
------------------- // unroll
Γ |- @M : T[x := M]


False @->
  (f : f @-> @False f) -> Type;


(f0 : (A : Type) -> A) =>
(f1 : (P : False0 -> Type) -> P f0) =>


@x : (P : T -> Type) -> P x;

u @->
  (P : Int -> Type) -> P (u P 1) -> Int;

Γ, x : x @-> T |- T : Type
-------------------------- // self
Γ |- x @-> T : Type

False @-> (f : f @-> @False f) -> Type;


False @-> (f : f @-> @False f) -> Type;

@self(False, f). (P : False -> Type) -> P f;

Unit I = _;

@self(Unit, u). (P : Unit -> Type) -> P unit -> P u;

(@Unit : Type) @-> Type;
(@Unit : Type) @-> () -> Type;

(@False : Type) @-> () -> Type;

(@Unit : Type) @=>
  (P : Unit -> Type) -> P (@unit @=> P => x => x) -> P u;

Γ, x : T |- T : Type
-------------------------- // self
Γ |- @x @-> T : Type

(@False) @-> (f : @f @-> False (@f1 : False f1) @=> f);

f : False ((@f1 : False f1) @=> f)

(@f1 : False f1) @=> f


Γ, x : A |- B : Type
-------------------------- // self
Γ |- (@x : A) @-> B : Type

Γ, x : T |- M : T
----------------------------- // fix
Γ |- (@x : T) @=> M : x @-> T

(Unit : Type) @-> Type;


(@False : Type) @=> (f : False) @->
  (P : False -> Type) -> P f;
(@Unit : Type) @=> (u : Unit) @->
  (P : Unit -> Type) -> P (@unit @=> P => x => x) -> P u;


(@False : (f : (f : _) @-> False) @-> Type) @->
  (f : (f : _) @-> False) @-> Type

(@False : ) @->
  (f : (@f : False ((@f1 : False f1) @=> f)) @-> )
(@False : Type) @=> (f : _) =>
  (P : ((@f : False f) @-> False f) -> Type) -> P f;


False @-> (f : f @-> False f) -> Type;

(@T_False : Type) @=>
  (I : @((@IT : Type) @=> T_False ->
    (I : IT) -> (False : T_False) @-> Type)) ->
  (False : T_False) @-> Type;

(False : ?) @->
  (I : @((@IT : Type) @=> False ==
    (I : IT) f @-> (P : False I -> Type) -> I P f)) -> Type;

(@False : Type) @=> (f : _) @>
  (P : ((@f : False f) @-> False f) -> Type) -> P f;

(@M : Type) @=>
  (I : @((@IT : Type) @=> M == (I : IT) -> Type)) -> Type;

@False @=> I => f @-> (P : False I -> Type) -> I P f;

(A, False : A) @=>
  _

(@False : (
  @T_f : Type = (@f : T_f) @-> False f;
  (f : ) -> Type
)) @=> (
  @T_f : Type = (@f : T_f) @-> False f;
  (f : (@f : T_f) @-> False f) -> Type
);

(@M : Type) @=>
  (I : @((@IT : Type) @=> M == (I : IT) -> Type)) -> Type;

(@M : Type) @=>
  (I : @((@IT : Type) @=> M == (I : IT) -> Type)) ->
  (x : M) @->
  (eq : @((@eqT : Type) @=>
    (eq : eqT) -> I _ x I eq == 1)) ->
  Int;

@T_False : Type =
  (False : T_False) @->
  (I : @((@IT : Type) @=> False == )) -> Type;
(False : T_False) @=> I =>
  (f : @False I) @-> (P : @False I -> Type) -> I _ P f;

@T_I (M : Type) : Type = M == (I : T_I M) -> Type;
@M : Type = (I : T_I M) -> Type;

@T_I (T_False : Type) : Type =
  T_False == _;
@T_False : Type =
  (I0 : T_I0 T_False) ->
  (False : T_False) @->
    (I1 : T_I1 T_False False) ->
    (f : f @-> @I1 False I1 f)
     Type;

(@False : T_False)
@False : T_False = I => (
  f @-> (P : False I -> Type) -> P f
);

@Unit (
  @I : (
    u @-> (P : Unit I -> Type) -> P (I (u @=> P => x => x)) -> P (I u)
  ) -> Unit I
) = u @-> (P : Unit I -> Type) -> P (I (u @=> P => x => x)) -> P (I u);

Unit = Unit (@I @=> x => x);
unit : Unit = u @=> P => x => x;

@Unit I =
  u @-> (P : Unit I -> Type) -> P (I (u @=> P => x => x)) -> P (I u);


read : (world : World, file : String) -> (world : World, content : String);
print : (world : World, message : String) -> World;
main : World -> World;

read : (world : &mut World, file : String) -> String;
print : (world : &mut World, message : String) -> ();


main world = (
  (world, hello) = read(world, "hello.txt");
  world = print(hello);
  (world, bronha) = read(world, "bronha.txt");
  print(world, bronha);
);

main world = (
  hello = read(world, "hello.txt");
  () = print(hello);
  bronha = read(world, "bronha.txt");
  print(bronha);
);


IO X : World -> (World, content : X)

main () = (
  hello = read(world, "hello.txt");
  () = print(hello);
  bronha = read(world, "bronha.txt");
  () = print(bronha);
  ()
);

main : IO ();

Grade

Γ |- A : Type  Γ |- n : Grade
-----------------------------
Γ |- M : A $ n

Γ, x : A $ n |- B : Type $ 0
------------------------------------
Γ |- ((x : A $ n) -> B $ m) : Type $ 0

Γ, x : A $ n |- M : B $ m
--------------------------------------------------
Γ |- (x : A $ n) => M : ((x : A $ n) -> B $ m) $ k

Γ |- M : ((x : A $ m) -> B $ n) $ 1  Γ |- N : $ n
--------------------------------------------------
Γ |- M N : ((x : A $ n) -> B $ m) $ k



f = x => x + x;
f = (x : Int) => x + x;

Γ |- M : A
Γ |- M : A $ n

f : (!x : Nat, !y : Nat, ?z : Nat = 1) -> Nat;

f (1, 2, 3);

1 ^ 1

(+) : (x : Nat, y : Nat) -> Nat &
(+) : (x : String, y : String) -> String;


S S S Z + S S Z = S S S S S Z
"abc" + "de" = "abcde"

(+) : (x : Nat, y : Nat) -> Nat &
(+) : (x : String, y : String) -> String;

(+) : ()

Linear HM == Mono Unification
Linear System F == Mono Unification
Multiplicative System F == Mono Unification + Intersection


(id : _A & _B $ 2) => ((id : _A) 1, (id : _B) "a")

(id : Int -> _A & String -> _B $ 2) => ((id : _A) 1, (id : _B) "a")

Nat<G> = (A : Type) -> (z : A $ 1) ->
  (s : (G : Grade) -> (A -> A) $ G) -> A;

(G : Grade) => (x $ G) => _;

(id : _A & _B $ 2) => (id 1, id "a")


Γ |- A : Type
-------------
Γ |- M : A

Γ |- A : Type $ 0  Γ |- G : Grade $ 0
-------------------------------------
Γ |- M : A $ G



Γ, x : A |- B : Type
------------------------
Γ |- (x : A) -> B : Type

(A : Type $ 1) => (x : A) => (
  (A) = A;
  x
);

(A : Type) => (x : A) => x;


Bool = (A : Type) -> A -> A -> (A, Garbage);
Bool = (A : Type) -> A -> A -> Weak A;

A ->
(A : Type $ 2) => (x : A) => ((x : A) => x) x;

((x : A) => M) N ==
  () <- weak A;
  M[x := N]

Γ |- M : (x : A) -> B ! Δ1  Γ |- N : A ! Δ2
-------------------------------------------
Γ |- M N : B[x := N] ! Δ1, Δ2, Weak

(x : Nat $ 2) => x + x;
(x0 : Nat) => (x1 : Nat) => (eq : x0 == x1) => x0 + x1;


id
  : (A : Type $ 2) -> (x : A) -> A;
  = (A : Type $ 2) => (x : A) => x;

(A : Type) -> (B : Type) ->
(eq : (P : Type -> Type) -> P A -> P B) ->
(x : A) -> B

Pair (A : Type) (B : Type) =
  (K : Type) -> (k : ((x : A) -> (y : B) -> K)) -> K;

Unit = (A : Type) -> ()
Exist = ((A : Type) -> (x : A) -> Unit) -> Unit
Weak (A : Type) =
  (G : Type, x : Exist)

(A : Type $ 2) => (x : A) => ((x : A) => x) x;
(A : Type $ 2) => (x : A) => (() = weak A; x);

(s : Socket $ 2) => (

)




add : (n : Nat) -> (m : Nat) -> Nat

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
ind : (b : Bool (n + 1)) ->
  (P : Bool n -> Type) -> P true -> P false -> P (lower b);

(x : Nat) -> (y : Nat) -> x *
(x : A $ 1) -> B ! Δ $ n

(x : A $ 2) -> B $ 2

(x : A $ 1) -(2)> B

(x : A $ 1) -[IO $ 2]> B
(x : A $ 1) -()> B

Γ |- M : P


(x : Int $ 2) => x + x;


Ref : {
  @Ref (A : Type) : Type$;
  make : {A} -> (value : A) -> Ref A;
  get : {A} -> (cell : Ref A) -> (cell : Ref A, value : A);
  set : {A} -> (cell : Ref A, value : A) -> (cell : Ref A);
} = _;

x = cell = (
  cell = Ref.set(cell, 1);
  (cell, value) = Ref.get(cell);
  cell
);

main : World$ -> World$;

read : (world : World$, file : String) -> (world : World$, content : String);
print : (world : World$, message : String) -> World$;

main : IO ()

main world = (
  (world, hello) = read(world, "hello.txt");
  world = print(world, hello);
  (world, bronha) = read(world, "bronha.txt");
  print(world, bronha);
);



map : {A B} -> (l : List A, f : (el : A) -> B) -> B;

map : {A B} -> (l : List {G} A $ 1, f : ((el : A $ 1) -> B $ 1) $ G) -> B $ 1;

map : {A B G} -> (l : List G A $ 1, f : ((el : A $ 1) -> B $ 1) $ G) -> B $ 1;
add : (l : List 1 A, a : Nat $ 1) = (l, a) =>
  map(l, (el => el + a) $ 1);


f = (a : Nat $ 0) => 1;

List L A = {K} -> (initial : K $ 1, fold : (acc : K, el : A) -> K $ L) -> K;

Type : Type

id : A. A -> A = x => x;
id : (A : Type) -> A -> A =
  (A : Type) => x => x;


forall A. A -> A
forall A -> A -> A

id : forall A. A -> A = A => (x : A) => x;

id : {A} -> (x : A) -> A;
id {A} x = x;

id : ?A -> (x : A) -> A;
id ?A x = x;

User : (User : Type & {
  make : (name : String) -> User;
}) = _;
User : Type & {
  make : (name : String) -> User;
} = _;
User : {
  @User : Type;
  make : (name : String) -> @User;
} = _;

id = (!x : Nat) => x;
x = id(x = 1);

f = (x : User) => x;

add (1, 2)
?add (1, _)

add 1 2
?add 1 _

pair _A 1 _A 2

<A> (x : A) -> A
<A> (x : A) => x;
<A> -> (x : A) -> A
<A> => (x : A) => A
id <A>

{A} (x : A) -> A;
{A} (x : A) => x;
{A} -> (x : A) -> A;
{A} => (x : A) => x;
id {A}

[A] (x : A) -> A;
[A] (x : A) => A;
[A] -> (x : A) -> A;
[A] => (x : A) => x;
id [A]

(?A) -> (x : A) -> A;
(?A) => (x : A) => x;

id ?A

-(IO)>
-[IO]>

`
~


id <A> x = x;

(<A : Int>, x : Int)
pair : <A>(x : A, y : A) -> Pair A B;

(==) : <A>(x : A, y : A) -> Bool;

(==) : <A>(x : A, y : A) -> Type &
(==) : <A : Eq>(x : A, y : A) -> Option (x == y);

x => y => (x == y : _A where _A == Type or _A == Option (x == y))

id (A : Type) (x : A) = x;


%macro (A : Type $ 1) =

x => %printf (x : _A)
x => _B x

when _A to Int == _B := Int.printf

x => Int.printf x

extract "/users/:id" : ("id", _ : _A)

"a" : Type | String

((x : "a") => _) ("a")

Either(A, B) =
  | ("left", A)
  | ("right", B);

Either(A, B) =
  | Left(A)
  | Right(B);


Either(A, B) =
  | (tag : "left", A)
  | (tag : "right", B);


x
| ("left", x) => _
| ("right", y) => _

(>) : <A>(x : A, y : A) -> Type &
(>) : <A : Cmp>(x : A, y : A) -> Option (x > y);

1 == 2 : Option (1 == 2)

(==) : <A>(x : A, y : A) -> Type
f = (x : 1 == 1) => x;

Eq A = {
  eq : (x : A, y : A) -> (x == y | x != y);
}
x => y => eq x y

f (eq x 1 | Some eq => eq);

pair <Int> (1, 2)

[%mode dynamic]
f = x => x;

x : Dyn = 1;

Int.add : (x : Int, y : Int) -> Int

Int.add (assert.Int x) : 1 ! Assert $ n

| "int" => (x : Int)




useless : (<A : Type>, x : A) -> (A : Type, x : A)
useless(1)


id ~x = 1

\(A)/ ->

id::[1]

id : <A>(x : A) -> A;
id <A> x = x;

id <A> x = x;

id ?Int 1;

{ x; y; } = { x = 1; y = 2; };


Id : Type = (A : Type) => A;

f (x : Int & x > 0) = (
  1
);

@id {Int} 1 = 1
id : forall a. a -> a
id (x : a) = x


f (id : Int -> 'A & String -> 'B $ 2) = (id 1, id "a")

f {G} l = _


f {1} [1] = _
add = a =>
  map(l, el => el + a);

map : {A B} -> (l : List A, f : ({G} -> ((el : A) -> B) $ G) $ 1) -> B;

map : {A B} -> (l : List A, f : (el : A) -> B) -> B;

id = (A : Type $ 0) => (x : A $ G) => x;

double = (x : Nat $ 2) => x + x;

id = (A : Type) =>

Linearity saves the day

Fix = (x $ 2 : Fix) -> ();
((x $ 4 : Fix) => x x);

case : (b : Bool) -> (A : Type) -> A -> A -> A;
Bool = (A : Type) -> A -> A -> A;

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
Bool = (P : Bool -> Type) -> P true -> P false -> P b;

Bool : Type
true : Bool
false : Bool

Bool = b @-> (P : Bool -> Type) -> P true -> P false -> P b;
true = (P : Bool -> Type) => (x : P true) => (y : P false) => x;


(x : $Socket)

(x $ 4 : Nat) =(2)> (x + x)


() -> @fix(S). S

T =
  @fix(S). (f : (A : Nat) -> Type $ 0) -> f 1;


Type : Type

(G : Grade) => (x $ G) =>

Γ | Δ, x : A |- M : B
------------------------------------
Γ | Δ |- (x : A) => M : (x : A) -> B


(A : Socket $ 2) =>
(A $ n) $ m
Socket = _ $ 1;
(x : Socket $ 2) => x;

Array : {
  Write : {
    @Write (A : Type) : Type;
  };
  Read : {
    @Read (A : Type) (x : Write A) : Type;
    split : <A>(x : Write A) -> (l : Read A x, r : Read A x);
    merge : <A>(x : Write A $ 0, l : Read A x, r : Read A x) -> (x : Write A);
  };
};


Γ |- A : Type   Γ |- n : Grade
------------------------------
Γ |- A $ n : Type

Γ |- M : A  M == N
------------------
Γ |- M + N : A $ 2



---------------
Γ |- A $ 1 == A

(x : _A $ _G) => x;
(x : _A $ _G) => x + x;
1 :: id ::

t :: id |- \0 -> t

x[open := t]

_A[open x/+2] `unify` x\+2

_A := x/+2[close +2]
_A := x/-1

x/+2[close +2][open x/+2]

x/+2[+2 := -1][-1 := x/+2]

(_ => x/-2)[open x/+2]
x/-2[Lift][open x/+2]

[open x/+2; id] |- _A `unify` [Free; Free]

A/-1 -> A/-2
(A/+2 -> A/+2)[close +2]

A/+2[close +2] ~~> A/-1
A/+2[id][close +2] ~~> A/-2

A => B => _C `unify` A => B => A/+2[id][close +2]

{} [id; id;] |- _C `unify` [id; id; close +2; id;] |- A/+2


A => (B => A/+2)[close +2]
A => B => A/+2[id]
_C := A/+2[id][close +2][id][id][-id][-id]
{} - [id;] |- A/+2[id][close +2]
{ +2 = 0; } - [id;] |- A/+2[id]
{ +2 = 0; } - [id; id;] |- A/+2 ~~> A/-2

A => A/-1

A => A/+2[close +2]

{} - [] |- A/+2[close +2]
{ +2 = 0; } - [] |- A/+2 ~~> A/0
{ +2 = 0; } - [id] |- A/+2

A/-2[id][open x/+2] ~~> A/+2

A/+2[close +2][open +2] ~~> A/+2

A/+2[id][close +2] ~~> A/-2
A/+2[id][close +2][id][open +2] ~~> A/+2
A/+2 ~~> A/-2 ~~> A/
[Free, Free] |- A/+1

x @
| a
| b


Free = +
Bound = -

+A
A => -A

λ.λ.\1

(λ.λ.\1) "a" "b"

"b" :: "a" :: [] |- \1 ~> "a"

codemod that tags every occurencce of identifier so that the dev needs to go and check the code, removing the annotation

Type\1
String\2
A\3

Sorry\2
@fix(False). (f : @self(f -> @unroll False f)) =>
  (P : (f : @self(f -> @unroll False f)) -> Type) -> P f

False : @self. _A[close +3]
f : @self. _B[close +4]

@unroll \+3 : _A
_A := (f : @self. _B[close +4]) -> Type
@unroll \+3 \+4 : Type
_B := @unroll \+3 \+4

False : @self. (f : @self. @unroll \-1 \-0) -> Type
f : @self. _C[close +5]

@unroll \+3 : (f : @self. @unroll \+3 \-0) -> Type
@unroll \+3 \+5 : Type

expected : @self. @unroll \+3 \-0
received : @self. _C[close +5]

@self. @unroll \+3 \-0 `unify` @self. _C[close +5]
@self. @unroll \+3 \-0 `unify` @self. _C[close +5]

(False : @self. (f : @self. @unroll False f) -> Type) =>
  (P : (f : @self(f -> @unroll False f)) -> Type) -> P f

(False : @self(False -> (f : @self. @unroll False f) -> Type)) =>
  (P : (f : @self(f -> @unroll False f)) -> Type) -> P f

False : @self. (f : @self. @unroll \-1 \-0) -> Type
f : _A

@unroll \+3 : (f : @self. @unroll \+3 \-0) -> Type
@unroll \+3 \+5 : Type

@self(False). (f : @self(f). @unroll False f) -> Type

False : @self. _A[close +3]
f : @self. _B[close +4]

@unroll \+3 : _A
_A := (f : @self. _B[close +4]) -> Type
@unroll \+3 \+4 : Type

_B := @self. @unroll \+3 \-0

@self. (f : @self. @unroll \+3 \-0) -> Type[close +4]


False : @self. (f : @self. @unroll \-1 \-0) -> Type
f : @self. _B
@self((f : @self(f -> _B)) -> @unroll \+3 \-0)

f : @self. _A[close +5]

@unroll \+3 : (f : @self. @unroll \+3 \-0) -> Type
@unroll \+3 \+5 : Type

@self. @unroll \+3 \-0 `unify` @self. _A[close +5]
(@unroll \+3 \-0)[open \+6] `unify` (_A)[close +5][open \+6]
(@unroll \+3 \-0) `unify` (_A)[close +5]
(@unroll \+3 \-0) `unify` (_A)[open \+5]

@self(False -> (f : @self. @unroll False f) -> Type)

False : _A
f : _B

@unroll \+3


@self. _C[close +3] `unify` @self. _A

False : _A

(False : @self(False -> (f : @self. @unroll False f) -> Type)) =>
  (P : (f : @self(f -> @unroll False f)) -> Type) -> P f

False : @self. (f : @self. @unroll \-1 \-0) -> Type)
f : @self. _B[close +5]


T[subst] === U[subst]
T === U

_ -> _A -> _A === _ -> \-0 -> \-1
(_A -> _A)[subst] === (\-0 -> \-1)[subst]
_A\+3 -> _A\+3 === \-0 -> \-1

_A\+3 := \-0

Unification

( + ) : Int -> Int -> Int;

x => x + 1

Γ, x : _A |- x + 1 : Int

_A := Int

incr : Int -> Int = x => x + 1;

map(x => x + 1)
(x : Int) => x + 1

(x => x) : 'a. 'a -> 'a
Γ, x : _A |- x : _A

id
  : (A : Type) -> (x : A) -> A
  = (A : Type) => (x : A) => x;

id(String) : ((x : A) -> A)[A := String]

f = (id : (A : Type) -> A -> A) => (id(1), id("a"))

3 [] {} |- \+3[close +3][open \+3]
4 [\+3 - 4] {} |- \+3[close +3]
5 [\+3 - 4] { +3 := -0 - 5 } |- \+3 ~> \-0
4 [\+3 - 4] { +3 := -0 - 5 } |- \+3 ~> \-0 ~> \+3

\+3[close +3][open \+3]
\+3[close +3][open \+3]

5 [\+3 - 4] { +3 := [\-0 - 3; -0 - 5] } |- \-0
4 [\+3 - 4] { +3 := [\-0 - 3; -0 - 5] } |- \-0 ~> \+3
3 [\+3 - 4] { +3 := [\-0 - 3; -0 - 5] } |- \-0 ~> \+3 ~> \-0

\+3[close +3][open \+3]
\-1[open \+3][close +3][open \+3]

Γ, open \+3, close +3, open \+3, close +4 |- \-0
Γ, open \+3, close +3, open \+3 |- \-0
Γ, open \+3, close +3 |- \+3
Γ, open \+3 |- \-0
Γ |- \+3

[] |- \+3[close +3]

[Type] |- (A : Type) -> ((x : A\+2) -> A\+2)[close]
[Type] |- (A : Type) -> ((x : A\+2) -> A\+2)[close]


\+3[close +3][open \+3]

expected : (A : Type) -> A -> A
received : (B : Type) -> B -> B

expected : (A : Type) -> \-1 -> \-2
received : (B : Type) -> \-1 -> \-2

(A : Type\+0) -> \+1 -> \+1
(A : Type) => (x : \-1 -> \-2) => (x : \-2 -> \-3)


(A : Type\+0) -> \-1
(A : Type) -> (\+1 -> \+1)[close]

(A : Type\+0) -> \-1 -> \-2
(B : Type\+0) -> _A -> _A

A := \-1

(A : Type\+0) -> \-1 -> \-2
(B : Type\+0) -> \-1 -> \-1


(\-1 -> \-2)[open +4]

\+4 -> \+4
_A -> _A

\+3[close +3][open \+3]

close +3 open \+3 |- \+3


\+3[close +3][open \+3]

[\+3] { +3 := -0 } |- \-0 ~> \+3 ~> -0

(\+3 -> \+3)[close +3][open \+3]
\+3 -> \+3[close +3][open \+3]

@self. @unroll \+3 \-0 `unify` @self. _A[close +5]
(@unroll \+3 \-0)[open \+6] `unify` _A[close +5][open \+6]
(@unroll \+3 \-0) `unify` _A[close +5]
(@unroll \+3 \-0)[open \+5] `unify` _A

|- @self. @unroll \+3 \-0 `unify`
|- @self. _A[close +5]

[] |- @self. @unroll \+3 \-0
[close +5; ] |- @self. _A

[open \+6; ] |- @unroll \+3 \-0
[close +5; open \+6; ] |- _A

_A := @unroll \+3 \-0[open \+5]

x = 1;
eq : x + 1 == 2 = refl;

x == 1;


f : (A : Type) -> (\+1 -> \+1)[close ] = _;
f

[Type] |- (A : Type) -> ((x : A\+1) -> A\+1)[close]

\+3[open \+3][close +3]

[] {} |- \+3[open \+3][close +3]
[] { +3 := -1 } |- \+3[open \+3]

{} |- \+3[close +3][open \+3]
{} |- \+3[\+3 := \-1][\-1 := \+3]
{ \-1 := \+3; } |- \+3[\+3 := \-1]
{ \-1 := \+3; \+3 := \-1; } |- \+3
{ \-1 := \+3; } |- \-1
{ } |- \+3

{} |- \+3[close +3][open \+3]
{} |- \+3[\+3 := \-1][\-1 := \+3]
{ \-1 := \+3; } |- \+3[\+3 := \-1]
{ \-1 := \+3; \+3 := \-1; } |- \+3
{ \-1 := \+3; \+3 := \+3; } |- \+3


{} |- \+3[close +3][open \+3 -> \+3]
{} |- \+3[\+3 := \-1][\-1 := \+3 -> \+3]
{ \-1 := \+3 -> \+3; } |- \+3[\+3 := \-1]
{ \-1 := \+3 -> \+3; \+3 := \-1; } |- \+3
{ \-1 := \+3 -> \+3; \+3 := \+3 -> \+3; } |- \+3

{} |- \+3[\+3 := \+3 -> \+3][\-1 := \+3 -> \+3]

{} |- \+3[\+3 := \-1][\-1 := \+3 -> \+3]

\+3[\+3 := \+3][\-1 := \+3]

\-1[open \+3][close +3][open \+3]

5 [\+3 - 4] { +3 := [\-0 - 3; -0 - 5] } |- \-1
4 [\+3 - 4] { +3 := [\-0 - 3; -0 - 5] } |- \-1 ~> \+3
3 [\+3 - 4] { +3 := [\-0 - 3; -0 - 5] } |- \-1 ~> \+3 ~> \-1

+1 |- (A : Type) -> \+1 -> \+1
+4 |- (A : Type) -> \+4 -> \+4

(A : Type) -> (\+1 -> \+1)[close +3]
(\-1 -> \-2)[open +3]


f : (Int\-1 -> Int\-2)[open Int\+3]
x : Int\-2[id][open Int\+3]

expected : Int\-1[open Int\+3]
received : Int\-1[id][open Int\+3]

2 [] |- (A : Type) -> A\-1 -> A\-2
2 [] |- (A : Type) -> _B -> _B

2 [] |- (A : Type) -> A\-1 -> A\-2
2 [] |- (A : Type) -> _B\+3 -> _B\+3

3 [open A\3; ] |- A\-1 -> A\-2
3 [open A\3; ] |- _B\+3 -> _B\+3

_B := A\-1
3 [A\3;] |- A\-1 -> A\-2
3 [A\3; A\3;] |- _B -> _B

3 [A\3;] |- A\-1
3 [A\3; A\3;] |- _B

_B := A\-1[close ]
2 [] |- (A : Type) -> _B[close] -> _B[shift][close]

3 [] |- (A\-1 -> A\-2)[open A\+3]
3 [] |- (_B[close] -> _B[shift][close])[open A\+3]

3 [open A\+3] |- A\-1 -> A\-2
3 [open A\+3] |- _B[close] -> _B[shift][close]

3 [open A\+3] |- A\-1
3 [open A\+3] |- _B[close]

3 [open A\+3] |- A\-1
3 [open A\+3; close] |- _B[]

3 [] |- (A\-1 -> A\-2)[open A\+3]
3 [] |- (_B -> _B)[close][open A\+3]

[] |- (A\-1 -> A\-2)[open A\+3]
[] |- (_B -> _B)[open A\+3]

[A\+3] |- A\-1 -> A\-2
[A\+3] |- _B -> _B

_B := A\-1[A\+3]![A\+3]

x => id(x)
x => x

[Int : Type] |- (x : Int\1 = _; x\1 : (Int\1)[lift])
[Int : Type; x : Int\1] |- (x\1 : (Int\2)[lift])

[] |- x\-1[y\-2][id][x\-1]
[x\-1] |- x\-1[y\-2][id]
[x\-1; id] |- x\-1[y\-2]
[x\-1; id; y\-2] |- x\-1
[x\-1; id] |- y\-2
[x\-1] |- y\-1
[] |- x\-1

1[2 . id][2 . id]
2[2 . id]
1

[] |- 1[2 . id][2 . id]
[2 . id] |- 1[2 . id]
[2 . id; 2 . id] |- 1
[2 . id] |- 2
[] |- 1

1[2[shift] . id]
2[shift]
3

[] |- 1[2[shift] . id]


[] |- 1[2 . id][1 . id]

[] |- 1[2[shift] . id]
[2[shift] . id] |- 1 ~> 2[shift]
[2[shift] . id] |- 2[shift]
[2[shift] . id] |- 2[2 . id]

[] |- 2[3 . id]
[2 . id] |- 2

[] |- -1[open +3]


\+3[close +3][open \+3]

4 [] {} |- \+3[close +3][open \+3]
5 [] { +4 : 4 } |- \+3[close +3]

4 [] |- \+3[close +3][open \+3]
4 [open \+3] |- \+3[close +3]
4 [close +3; open \+3] |- \+3
4 [open \+3] |- \-1
4 [] |- \+3

[] [] |- \+1[close +1][open \+1]
[open \+1] [] |- \+1[close +1]
[open \+1] [close +1 at 1] |- \+1
[open \+1] [] |- \-1
[] [] |- \+1

[] [] |- \+1[close +1][shift]

((A : Type) -> \+2 -> \+2)[shift]


\+1[close] = \-1
\+2[close] = \+1
\+3[close] = \+2

\-1[shift] = \-2
\-2[shift] = \-3

(\+2 -> \+2)[close +2]
\+2[close +2] -> \+2[close +2][shift]
\-1 -> \-2

(\+2 -> \+2)[close][close]
(\+2[close] -> \+2[close][shift])[close]
(\+2[close][close] -> \+2[close][shift][close][shift])


(A : Type) -> (\+2 -> \+2)[close +2]

\-1[open t] = t
\-(n + 1)[open t] = \-n

\+n[+n close -m] = \-m

l |- (A -> B)[s]
l |- A[s] -> B[open \+l][s][shift]

(\+2 -> \+2)[close +2]
(\+2[close +2] -> \+2[open \+l][close +2][shift])
(\+2[close +2] -> \+2[close +2][shift])

[] [] |- \+2[open \+l][close +2][shift]
[open \+l; noop; shift] [noop; close +2; noop] |- \+2
[open \+l; noop; shift] [noop; close +2; noop] |- \+2

[open \+l; shift] [close +2] |- \+2
[shift] [close +2] |- \-1

\+2[close][close] -> \+2[open \+l][close][open \+l][close]
\-2 -> \+1[close][open \+l][close]

(a -> b)[s]
(a[s] -> b[lift(s)])

[] |- (A : Type) -> A\-1
[] |- (A : Type) -> _A

[open \+2] |- (A : Type) -> A\-1
[open \+2] |- (A : Type) -> _A

(\+2 -> \+2)[close +2]
\+2[close +2] -> \+2[open \+l][close +2]

// TODO: exception?
\-1 == \-1
\-(n + 1)[lift(s)] == \-n[s][shift]

(\+2 -> \+2)[close +2]
(\+2[close +2] -> \+2[lift(close +2)])
(\+2[close +2] -> \+2[close +2][shift])

(\-1 -> \-2)[open A]
(\-1[open A] -> \-2[lift(open A)])
(\-1[open A] -> \-1[open A][shift])

(A : Type) -> (\+1 -> \+1)[close]
(A : Type) -> \+1[close] -> \+1[close][shift]
(A : Type) -> \-1 -> \-2

((A : Type) -> \-1 -> \-2)
(\-1 -> \-2)[1 . shift]

((A : Type) -> \+2 -> \+2)[shift]
((A : Type) -> \+3 -> \+3)

0 [] { 3 : 3 } |- \+3



[] |- (\+2 -> \+2)[close +2]
[close +2] |- \+2 -> \+2

[] |- (\+2 -> \+2)[close +2]
[close +2] |- \+2 -> \+2

\+2[close +2] -> \+2[open \+l][close +2]

[] |- (\+2 -> \+2)[close +2]
[close +2] |- \+2 -> \+2


[\+1] [+2] |- \-1


(\-1 -> \-2)[open ]

(A : Type) -> (\+2 -> \+2)[close +2]

[] |- (\+2 -> \+2)[close +2]
[close +2] |- \+2 -> \+2
[open +l; lift([close +2])] |- \+2


(λa)[s]
λ(a[+l . ])
[open +l; lift([close +2])] |- \+2

[open +l; lift([close +2])] |- \+2

[open \+l] [] |- \+2

[\+1] [+2] |- \-1 -> \-2

(\-1 -> \-2)[id]
\-1[id] -> \-2[open \+l][id][shift]

\-1 -> \-2


(λa)[s]
λ(a[+l . ])

[] |- \-1[open a[open b]]
[a[open b]] |- \-1 ~> a[open b]
[open b; _] |- (λ-2)

[] |- \-1[open a[open b]]

// fast / naive enough?
[open \+2; open \+1] {} |- \+1[close +1][open \+1]
[open \+1; open \+2; open \+1] {} |- \+1[close +1]
[open \+1; open \+2; open \+1] { 1 : [3] } |- \+1
[open \+1; open \+2; open \+1] [] |- \-1
[_; _; _] [] |- \+1


[open \+2; open \+1] {} |- \+1[open \+1][close +1][open \+1]
[open \+1; open \+2; open \+1] {} |- \+1[open \+1][close +1]
[open \+1; open \+2; open \+1] { 1 : [3] } |- \+1[open \+1]
[open \+1; open \+1; open \+2; open \+1] { 1 : [3] } |- \+1
[open \+1; open \+1; open \+2; open \+1] { 1 : [3] } |- \-2


[open \+2; open \+1] { 1 : [2] } |- \+1[open \+1]
[open \+1; open \+2; open \+1] { 1 : [2] } |- \+1
[open \+1; open \+2; open \+1] { 1 : [2] } |- \+1


[open \+2; open \+1] {} |- \+1[close +1][open \+1]
[open \+1; open \+2; open \+1] {} |- \+1[close +1]

[open \+1; open \+2; open \+1] { 1 : 3 } |- \+1
[open \+1; open \+2; open \+1] { 1 : 3 } |- \-1
[open \+1; open \+2; open \+1] { 1 : 3 } |- \+1

[open \+2; open \+1] [none; none] |- \+2[close +2][open \+2]
[open \+2; open \+2; open \+1] [] |- \+2[close +2]

[open \+2; open \+2; open \+1] { 2 : } |- \+2[close +2]

// capture entire stack
[open \+2; open \+1] {} |- \+1[open \+1][close +1][open \+1]
[open \+1; open \+2; open \+1] {} |- \+1[open \+1][close +1]
[open \+1; open \+2; open \+1]
{ 1 : ([open \+1; open \+2; open \+1], {}) } |- \+1[open \+1]
[open \+1; open \+1; open \+2; open \+1]
{ 1 : ([open \+1; open \+2; open \+1], {}) } |- \+1
[open \+1; open \+2; open \+1] {} |- \+1
[open \+1; open \+2; open \+1] {} |- \-1

// shift stack
[open \+2; open \+1] {} |- \+1[open \+1][close +1][open \+1]
[open \+1; open \+2; open \+1] {} |- \+1[open \+1][close +1]
[open \+1; open \+2; open \+1] { 1 : (3, {}) } |- \+1[open \+1]
[open \+1; open \+1; open \+2; open \+1] { 1 : (3, {}) } |- \+1
[open \+1; open \+2; open \+1] {} |- \+1
[open \+1; open \+2; open \+1] {} |- \-1

\+1[open \+1][close +1][open \+1]
\+1[close +1][open \+1]
\-1[open \+1]
\+1


\-1[shift][open \+2][open \+1]

[open \+2; open \+1] |- \-1[shift]
[open \+1] |- \+1


\-1[open a] ~> a
\-(n + 1)[open a] ~> \-n

(λa)[+1 close -1]
λ(a[+l][+1 close -2])


(λa)[+1 close -1]
λ(a[+1][+1 close -2])

s1 λe1 = s2 λe2
lift s1 e1 = lift s2 e2

(λe1)
open t (λλ-2) = λλ-2


[noop; open +2; open +1]
lift s (-1) = -1
lift s (-(n + m)) =

-2[open +1][open +2]
-2[-l open +1]

[+1 close -2]

t[s][]
(λa)[+1 close -2]
λ(a[+l][close +1])

(λa)[close +1]
λ(a[+l][close +1])

lift(, 1) = 1
lift(open +n, n + 1) = shift(s(n))

lift(open +, 1) = 1
lift(open +n, n + 1) = shift(s(n))

lift(s, 1) = 1
lift(s, n + 1) = shift(s(n))

\-1[shift][open \+2]


2 [\+2; \+1] {} |- \+1[open \+1][close +1][open \+1]
2 [\+1; \+2; \+1] {} |- \+1[open \+1][close +1]
2 [\+1; \+2; \+1] { 1 : (2, 3, {}) } |- \+1[open \+1]
2 [\+1; \+1; \+2; \+1] { 1 : (2, 3, {}) } |- \+1
2 [\+1; \+2; \+1] {} |- \-1

2 [\+2; \+1] {} |- (λ\+1)[close +1][open \+1]
2 [\+1; \+2; \+1] {} |- (λ\+1)[close +1]
2 [\+1; \+2; \+1] { 1 : (2, 3, {}) } |- λ\+1
3 [\+2; \+1; \+2; \+1] { 1 : (2, 3, {}) } |- \+1
2 [\+1; \+2; \+1] {} |- \-1
2 [\+2; \+1] {} |- \+1

2 [\+1; \+2; \+1] { 1 : (3, {}) } |- \+1[open \+1]
2 [\+1; \+1; \+2; \+1] { 1 : (2, 3, {}) } |- \+1
2 [\+1; \+2; \+1] {} |- \-1


1 |- λ((\-1 \+2)[close +2])

(λ\+1)[close +1][open \+1]

(λ-1)[close +1] = (λ-1)[close +1]
(-1[+l][close +1][shift]) = (-1[+l][close +1][shift])

(λ+1)[close +1] ~~> λ-2

// colision inside of lambda related to open
(λa)[s]
λ(a[+l][])
closed[s][shift]


\-1[open \+l][shift]


1 2 => x y

1 |- (x => (x\+2 y\-2)[close +2 to -1])[open -1 to y\+1]
// entering a binder requires to shift all free negative variables
// the right side on open is locally closed, so only shift the left
// the left side on close is locally closed, so only shift the right
1 |- x => (x\+2 y\-2)[close +2 to -1][open -2 to y\+1]
1 |- x => (x\+2[close +2 to -1] y\-2[close +2 to -1])[open -2 to y\+1]
1 |- x => (x\-1 y\-2)[open -2 to y\+1]
1 |- x => (x\-1[open -2 to y\+1] y\-2[open -2 to y\+1])
1 |- x => x\-1 y\+1

// should definitely be true
(A : Type) -> \-1 -> \-2 `unify` (A : Type) -> _A -> _A
// solution, open and invoke a level in the context
2 |- (A : Type) -> \-1 -> \-2 `unify` (A : Type) -> _A -> _A
3 |- (\-1 -> \-2)[open -1 to \+3] `unify` (_A -> _A)[open -1 to \+3]
3 |- \+3 -> \+3 `unify` _A -> _A


// should ALWAYS be (y => x => x\-1 y\-2)
l |- (y => (x => x\-1 y\+2)[close +2 to -1])
// follow the steps and you will get to this
l + 2 |- (x\+(l + 2) y\+2)[close +2 to -2][open -2 to \+(l + 1)]
// what happens if l is 0?
2 |- x\+1 y\+1
// what happens if l is 1?
3 |- x\+3 y\+3

2 |- (x\+2 \+2)[open -2 to \+1][close +2 to -2]
2 |- (x\-2 y\-2)


l |- (y => (x => x\-1 y\+2)[close +2 to -1 at l + 1])
l + 1 |- (x => x\-1 y\+2)[close +2 to -1 at l + 1][open -1 to \+(l + 1)]
l + 2 |- (x\-1 y\+2)[open -1 to \+(l + 2)][close +2 to -2 at l + 1][open -2 to \+(l + 1)]
l + 2 |- (\+(l + 2) y\+2)[close +2 to -2 at l + 1][open -2 to \+(l + 1)]
// what happens if l is 0?
2 |- (\+2 y\+2)[close +2 to -2 at l + 1][open -2 to \+(l + 1)]

// should ALWAYS be (y => x => x\-1 y\-2)
l |- (y => (x => x\-1 y\+2)[close +2 to -1])
l + 1 |- (x => x\-1 y\+2)[close +2 to -1][open -1 to \+(l + 1)]
l + 2 |- (x\-1 y\+2)[open -1 to \+(l + 2)][close +2 to -2][open -2 to \+(l + 1)]
l + 2 |- (x\-1 y\+2)[open -1 to \+(l + 2)][close +2 to -2][open -2 to \+(l + 1)]

l |- (y => (x => x\-1 y\+2)[close +2 to -1])

// should ALWAYS be (y => x => x\-1 y\-2)
l |- (y => (x => x\-1 y\+1)[close +1 to -1])
l + 1 |- (x => x\-1 y\+1)[close +1 to -1][open -1 to \+(l + 1)]
l + 2 |- (x\-1 y\+1)[open -1 to \+(l + 2)][close +1 to -2][open -2 to \+(l + 1)]
l + 2 |- (x\-1 y\+(l + 1))[open -1 to \+(l + 2)][close +1 to -2][open -2 to \+(l + 1)]

// l = 0
2 |- (x\-1 y\+1)[open -1 to \+2][close +1 to -2][open -2 to \+1]
2 |- (x\+2 y\+1)

// l = 1
3 |- (x\-1 y\+1)[open -1 to \+3][close +1 to -2][open -2 to \+2]
3 |- (x\+3 y\+2)

// should ALWAYS be (y => x => x\-1 y\-2)
l |- (y => (x => x\-1 y\+2)[close +2 to -1])
l + 1 |- (x => x\-1 y\+2)[close +2 to -1][open -1 to \+(l + 1)]
l + 2 |- (x\-1 y\+2)[open -1 to \+(l + 2)][close +2 to -2][open -2 to \+(l + 1)]

// l = 0, leads to [close +2] at level 1, which is weird
// reminds me of escaping the scope
1 |- (x => x\-1 y\+2)[close +2 to -1][open -1 to \+1]



1 |- (x => x\-1 y\+2)[close +2 to -1][open -1 to \+1]

3 |- x\+3 y\+2


// should ALWAYS be (y => x => x\-1 y\-2), when l > 1
l |- (y => (x => x\-1 y\+2)[close +2 to -1])

(y => (x => x\-1 y\+2)[close +2 to -1])


l + 2 |- (x\-1 y\+(l + 1))[open -1 to \+(l + 2)][close +1 to -2][open -2 to \+(l + 1)]

(x\-1 y\+(l + 1))[open -1 to \+(l + 2)][close +1 to -2][open -2 to \+(l + 1)]
(x\+(l + 2) y\+l)

(x\+(l + 2) y\+(l + 1))


(x\+(l + 2) y\+(l + 1))[close +(l + 2) to -1]
(x\+(l + 2) y\+(l + 1))


l |- (y => (x => x\-1 y\+2)[close +l to -1])
l + 1 |- (x => x\-1 y\+2)[close +l to -1]

l |- (y => (x => x\-1 y\+2)[close +2 to -1])
l + 2 |- (x\+(l + 2) y\+(l + 1))

l + 2 |- (x\-1 y\+(l + 1))[open -1 to \+(l + 2)][close +1 to -2][open -2 to \+(l + 1)]


(x\+(l + 2) y\+(l + 1))[close +(l + 2) to -1]
(x\-1 y\+(l + 1))[open -2 to +]

//
l |- (y => (x => x\-1 y\+2)[close +2 to -1])
l + 2 |- (x\+(l + 2) y\+(l + 1))


l |- (y => (x => x\-1 y\+(l + 2))[close +(l + 2) to -1])
l + 1 |- (y => (x => x\-1 y\+(l + 2))[close +(l + 2) to -1])

//
l + 2 |- (\-1 \+2)[open -1 to \+(l + 2)][close +2 to -2][open -2 to \+(l + 1)]

l + 2 |- (\-1 \+2)[open -1 to \+(l + 2)][close +2 to -2][open -2 to \+(l + 1)]


l + 2 |- \+(l + 2) \+2[open -1 to \+(l + 2)]

//
l |- (y => (x => x\-1 y\+(l + 2))[close +(l + 2) to -1])
l + 1 |- (x => x\-1 y\+(l + 2))[close +(l + 2) to -1][open -1 to +(l + 1)]
l + 2 |- (x\-1 y\+(l + 2))[open -1 to +(l + 2)][close +(l + 2) to -2][open -2 to +(l + 1)]


0 |- (y => (x => x\-1 y\+1)[close +1 to -1])


0 |- (y => (x => x\-1 y\+1)[close +1 to -1])
l |- (y => (x => x\-1 y\+(l + 1))[close +(l + 1) to -1])

l |- (z = _; y => (x => x\-1 y\+(l + 1))[close +(l + 1) to -1])

(z = _; y => (x => x\-1 y\+1)[close +1 to -1])

0 [] [] {} |- (y => (x => x\-1 y\+1)[close +1 to -1])
1 [back] [open \+1] {} |- (x => x\-1 y\+1)[close +1 to -1]
1 [back; back] [open \+1] { +1 := ({}, -1 ~> \+1) } |- x => x\-1 y\+1
2 [] [open \+2; open \+1] { +1 := ({}, -1 ~> \+1) } |- x\-1 y\+1
2 [] [open \+2; open \+1] { +1 := ({}, -1 ~> \+1) } |- x\+2 y\+1

0 [] [] |- (y => (x => x\-1 y\+1)[close +1 to -1])
0 [] [] |- (y => (x => x\-1 y\+1)[close +1 to -1])


0 [] [] {} |- (y => (x => x\-1 y\+1)[close +1 to -1])
1 [back] [open \+1] {} |- (x => x\-1 y\+1)[close +1 to -1]
1 [back; back] [open \+1] { +1 := ({}, -1 ~> \+1) } |- x => x\-1 y\+1

(y => (x => x\-1 y\+2)[close +2 to -1])


(y => (x => x\-1 y\+1)[close +1 to -1])
(y => (x => (x\+2[close +2 to -1]) y\+1)[close +1 to -1])

(y => (x => x\-1 y\l+2)[close l+2 to -1])
(y => (x => x\-1 y\l+2)[close l+2 to -1])

[] [] |- (y => (x => x\-1 y\+1)[close +1 to -1])
[] [\+1] |- (x => x\-1 y\+1)[close +1 to -1]
[] [\+1] |- x => x\-1 y\+1
[] [\+2; \+1] |- x\-1 y\+1
  [y\+1] [\+2; \+1] |- x\+2
  [] [\+2; \+1] |- y\+1

[] [] |- λ(λ(\-1 \+1))[+1 := -1]
[] [\+1] |- (λ\-1 \+1)[+1 := -1]
[] [\+1] |- λ\-1 \+1
[] [\+2; \+1] |- \-1 \+1
  [\+1] [\+2; \+1] |- \-1 ~> \+2
  [] [\+2; \+1] |- \+1

[] [\+1] |- (x => x\-1 y\+1)[close +1 to -1]
[] [\+1] |- x => x\-1 y\+1
[] [\+2; \+1] |- x\-1 y\+1
  [y\+1] [\+2; \+1] |- x\+2
  [] [\+2; \+1] |- y\+1



[] |- _A[-1 := \+2] === +2


[] |- _A === +2[+2 := -1]

[] |- _A === \+1[+1 := \-1]
[] |- _A === \-1

l |- λ(_A λ(\-1 \+1))[+1 := -1]

0 |- (x = _; y => (x => x\-1 y\+2)[)


0 |- ((z => y => (x => x\-1 y\+2)[close +2 to -1]) _)

((z => y => (x => x\-1 y\+2)[close +2 to -1]) _)
(z => y => (x => x\-1 y\+2)[close +2 to -1])[open -1 to _]
(z => y => (x => x\-1 y\-2))

y => _A[close +2 to -1] `unify` x => x\-1
0 |- y => _A[close +2 to -1] `unify` x => x\-1


1 |- x => \+1[close +2 to -1]

(((1 z) => (2 y) => ((3 x) => x\-1 y\+2)[close +2 to -1]) _)
((2 y) => ((3 x) => x\-1 y\+2)[close +2 to -1])[open -1 to _]
((1 y) => ((2 x) => x\-1 y\+2[close +2 to -2][open -3 to _]))
(1 y) => ((2 x) => x\-1 y\-2)


(((1 z) => (2 y) => ((3 x) => x\-1 y\+2)[close +2 to -1]) _)
((2 y) => ((3 x) => x\-1 y\+2)[close +2 to -1])[open -1 to _]

y => _A[close +2 to -1] `unify` x => x\-1


l |- (A : Type) -> (_A -> _A)[close +(l + 1) to -1] `unify` (A : Type) -> A\-1 -> A\-2
l + 1 |- (_A[close +(l + 1) to -1] -> _A[close +(l + 1) to -2]) `unify` A\-1 -> A\-2
  l + 1 |- (_A[close +(l + 1) to -1]) `unify` A\-1
  l + 1 |- _A `unify`

  l + 1 |- A\-1[open -1 to \+(l + 1)][close +(l + 1) to -2] `unify` A\-2
  l + 1 |- A\-2 `unify` A\-2

A\-2[open -2 to \+(l + 1)][open -1 to \+(l + 1)]

A\-2[open \+(l + 1)][to \+(l + 2)]

(A : Type) -> (A\+1 -> A\+1)[from +1]

((A : Type) -> A\-1)[to \+2]

(A : Type) -> A\+1[from +1] -> A\+1[lift(from +1)]

(A : Type) -> A\+1[from +1] -> A\+1[lift(from +1)]

A\+1[from] = A\-1
A\+2[from] = A\+1

lift s \-(n + 1) = s \-n
lift s +n = s +n | \-m => \-(m + 1)

((B : Type) -> (A\-2 B\-1))[to f]
((B : Type) -> (A\-2 B\-1)[lift(to f)])
((B : Type) -> A\-2[lift(to f)] B\-1[lift(to f)])
((B : Type) -> A\-1[to f] B\-1)
((B : Type) -> f B\-1)

[to \-1; to a; to b]
[from; from; none]

l |- \+1

(B : Type) -> (A\-2[open f] B\-1)

[close; close; close] |- (A : Type) -> A\+4[close]
[close; close; close; close] |- A\+4 ~> A\-1


lift s +(n + 1) = s +n | \-m => \-(m + 1)

0 |- λ(λ+1)[close] ~~> λλ-2
0 |- λ(λ+1)[close]
     λλ+1[lift close]
     λλ+1[close][shift]
     λλ-2

lift s l \-(n + 1) = s +l \-n
lift s l +n = s +(l + 1) +n | \-m => \-(m + 1)

close l +l = \-1

l |- λ(λ+(l + 1))[close] ~~> λλ-2
l |- λ(λ+(l + 1))[close]
     λλ+(l + 1)[lift close]
     λλ-2


0 |- (x = _; (λ(λ+2)[close])[close]) ~~> λλ-2

1 |- λ(λ+2)[close] ~~> λ(λ+2[lift(close)])
1 |- λ(λ+2)[close] ~~> λ(λ+1[close])

λ(_A _A)[close] `unify` λ(+1 +1)[close]
λ(_A _A)[close] `unify` λ(+1 +1)[close]

((A : Type) -> A\+4[close])

A\+1[close] = A\-1
A\+2[close] = A\+2

A\+2[lift(close)] = A\-2
A\+3[lift(lift(close))] = A\-3

((B : Type) -> (A\-2 B\-1))[to f]


(λ(λ+2)[close])[close] ~~> λλ-2
λ(λ+2)[close][lift close]
λλ+2[lift close][lift (lift close)]

0 |- λ(λ+1)[close]
     λλ+1[lift close]
     λλ+1[close][shift]
     λλ-2

0 |- (λ(λ+2)[close])[close]
1 [] [close +1] |- λ(λ+2)[close]
1 [open \-1] [close +1] |- (λ+2)[close]
1 [open \-1] [close +1] |- (λ+2)[close]

λ.(λ.+2[close])[close]
λ.(λ.+1[lift close])
λ.(λ.-2)



\-1[lift s] = \-1
\-(n + 1)[lift s] = \-n[s][shift]

a[lift s]
// relevant property is that x doesn't appear in s
a[open x][s][close x]

-1[open x][s][close x] = x[s][close x] = x[close x] = -1
-2[open x][s][close x] = -1[s][close x] =
                         -1[close y][close x] = -1[close x] = -2
                         -1[open a][close x] = a[close x] = a

+y[open x][s][close x] = +y[s][close x]
+y[open _][close x] = +y
+y[close y][close x] = -1[close x] = -2

\-1[incr][-2 open a][decr] = \-2[open a][decr] = \-2[decr] = \-1
\-2[incr][open a][decr]

λ.(λ.-2)

+2[close][close] = \-1

[] [close] |- λ(λ+2)[close]
[free] [close] |- (λ+2)[close]
[free] [close; close] |- λ+2
[free; free] [close; close] |- +2


open t \-1 = t
open _ \-(n + 1) = \-n

close \+1 = \-1
close \+(n + 1) = \+n

lift _ \-1 = \-1
lift s \-(n + 1) = s \-n
lift s \+n = s +n | \-m => \-(m + 1)


λ.(λ.+2[close])[close]
λ.λ.+1[lift close]
λ.λ.-2

(λ.(λ.(λ.+2[close])[close])[close]) _
(λ.(λ.+2[close])[close])[close][open _]
λ.(λ.+2[close])[close][lift close][lift (open _)]
λ.(λ.-2)[lift close][lift (open _)]

(λ.(λ.(λ.+3[close])[close])[close]) _
(λ.(λ.+3[close])[close])[close][open _]


λ.(λ.+2[close])[close]
λ.(λ.+2[close][lift close])
λ.(λ.-2[lift close])
λ.(λ.-1)

λ.λ.(+2 +1)[close]

(λ+1.λ+2.+3) a

(λ.+2[close +2])

Teika

Button
  : () -[Database]> React.Component
  = () => {
  const x = get();
  return (<div> {x} </div>)
};

Joshua's

## Chapter {{pinned}}

### Abc

BBBBB

### Def

AAAAA

#### Def concepts

... ai puts here

AI optimizer

Valid Transformations

pred (succ x)

- max term size
- locality / proxy accumulate de-bruijin
- linearity / variable grading
- total number of reduction



(x => M) N
M[x := N]

(x => x x) N(10)
N N

Autocomplete, Code quality suggestion

Github find all PR / patches, trim many features, rank developers,

De-bruijin needs data

(λ.(λ.(λ.+1))[close +1]) a
(λ.(λ.+1))[close +1][open a]
λ.(λ.+1)[lift (close +1)][lift (open a)]
λ.λ.+1[lift (lift (close +1))][lift (lift (open a))]
λ.λ.-3[lift (lift (open a))]
λ.λ.-1[open a]
λ.λ.a


(λ.(λ.(λ.+3[close +3]))) a
(λ.(λ.+3[close +3]))[open a]
λ.(λ.+3[close +3])[lift (open a)]
λ.λ.+3[close +3][lift (lift (open a))]
λ.λ.-1[lift (lift (open a))]
λ.λ.-1

0 |- (λ.(λ.(λ.+3[close +3]))) a
0 |- (λ.(λ.+3[close +3]))[open a]
[] [] |- (λ.(λ.+3[close +3]))[open a]

0 [] [] |- (λ.(λ.(λ.+3))) a
0 [] [] |- (λ.(λ.+3))[a]
1 [a] [1] |- λ.(λ.+3)
2 [a; +2] [1; 2] |- λ.+3
3 [a; +2; +3] [1; 2; 3] |- +3

λ(1).+1 +1
λ(1)._A _A


(x = _; y = λ(2).+2 +2; +3)

(λ(1).(λ(2).+2) (λ(2).+2 +2)) _
((λ(2).+3) (λ(2).+2 +2))[1 | _]
((λ(2).+3) (λ(2).+2 +2))[1 | _]
(+2[2 | λ(2).+2 +2])[1 | _]
+2[2 | λ(2).+2 +2][2 | _]
+2[2 | λ(2).+2 +2][2 | _]


(λ(1).λ(2).+2 +2) _
∀(2).+2 +2
[-1]  |- (λ.(λ.+3))[open a]

(λ(1).(λ(2).(λ(3).+3))) a

0 [] [] |- (λ(2).(λ(3).+3))[a]
1 [a] [a] |- λ(2).λ(3).+3
2 [a; +2] [1; 2] |- λ(3).+3
3 [a; +2; +3] [1; 2; 3] |- +3
(λ(2).(λ(3).+3))[open a]



v <= l
-------
l |- +v


v |- b
------------
l |- λ(v). b




[] |- (λ(3).(λ(4).+2))[2 | a]


[] |- (λ(3).(λ(4).+2))[2 | a]

(λ(1).+1 +1) (λ(2).+2)
(λ(2).+2 +2)
(+2 +2)[2 := λ(1).+1]
(λ(1).+1) (λ(1).+1)
+1[1 := λ(1).+1]
λ(1).+1

x = _;
(λ(1).+1 _A)


[] |- λ(1).+1 === λ(2).+2
[] |- λ(1).+1 === [] |- λ(2).+2
[-1] |- +1 === [] |- λ(2).+2


λx.a `unify` λy.b
a[x := z] `unify` b[y := z]
_A `unify` b[y := x]


[] |- λ.+1[close +2] === [] |- λ.+2[close +2]

[] |- λ.+1[close +1] === [] |- λ.+2[close +2]
[] |- +1[close +1] === [] |- +2[close +2]
[close +1] |- +1 === [close +2] |- +2
[close +1] |- -1 === [close +2] |- -2

[] |- λ.(+1 (λ.+1))[close +1] === [] |- λ.(+3 (λ.+3))[close +3]
[] |- λ.(_A (λ._A))[close +1] === [] |- λ.(+3 (λ.+3))[close +3]
[] |- λ.(_A (λ._A))[close +1] === [] |- λ.(+3 (λ.-2))[close +3]
[] |- (_A (λ._A))[close +1] === [] |- (+3 (λ.-2))[close +3]
[close +1] |- _A (λ._A) === [close +3] |- +3 (λ.-2)
  [close +1] |- _A === [close +3] |- +3
  _A := +3[close +3][open \+1]
[close +1] |- λ.+3[close +3][open \+1] === [close +3] |- λ.-2
[lift (close +1)] |- +3[close +3][open \+1] === [lift (close +3)] |- -2
[close +3; open \+1; lift (close +1)] |- +3 === [lift (close +3)] |- -2
[open \+1; lift (close +1)] |- -1 === [lift (close +3)] |- -2
[lift (close +1)] |- +1 === [lift (close +3)] |- -2
[] |- -2 === [lift (close +3)] |- -2

[lift [close +1]] |- +2[close +2][open \+1] === [lift [close +2]] |- +2
[close +2; open \+1; close +1] |- +2 === [close +2] |- +2


[] |- λ.(_A (λ._A))[close +1] === [] |- λ.(-1 (λ.+3))[close +3]
[] |- (_A (λ._A))[close +1] === [] |- (-1 (λ.+3))[close +3]
[close +1] |- _A (λ._A) === [close +3] |- -1 (λ.+3)
  [close +1] |- _A === [close +3] |- -1
  _A := -1[close +3][open \+1]

[close +1] |- λ.-1[close +3][open \+1] === [close +3] |- (λ.+3)
[lift (close +1)] |- -1[close +3][open \+1] === [lift (close +3)] |- +3
[close +3; open \+1; lift (close +1)] |- -1 === [lift (close +3)] |- +3
[] |- -2 === [] |- -2


line 15, col 2

> f expr expr2
    ^  ^

Message

expected : Option Int
received : Option String

Dynamic

[@mode dynamic]

l => l.map(x => x + 1);
l => List.map(l, x => x + 1);

f = x => print(cast x);

Working

Id = (A : Type) -> A;
x : Id Int = _;
(x : _A);

[] |- _A === Id Int

expected : \-1[(open \+2) :: lift (open \+1)]
received : \-2[(open \+3) :: lift ((open \+2) :: lift (open \+1))]

expected : \-0[(open \+4) :: lift ((open \+3) :: lift ((open \+2) :: lift (open \+1)))]
received : \-0[(open \+3) :: lift ((open \+2) :: lift (open \+1))]

expected : \-0[(open \+4) :: lift ((open \+3) :: lift ((open \+2) :: lift (open \+1)))]
received : \-0[(open \+3) :: lift ((open \+2) :: lift (open \+1))]

expected : ((x : ) -> \-1)[(open \+3) :: lift ((open \+2) :: lift (open \+1))]
received : ((x : ) -> \-1)[(open \+2) :: lift (open \+1)][(open \+3) :: lift ((open \+2) :: lift (open \+1))]

annot : ((A : \+1) -> (x : \-0[(open \+4) :: lift ((open \+3) :: lift ((open \+2) :: lift (open \+1)))]) -> \-1)[(open \+3) :: lift ((open \+2) :: lift (open \+1))]

Effect

x : IO(Result(String, Error))
x : Result(IO(String), Error)

Eff l r = Raw_eff (sort_uniqe l) r;

x : Eff [IO; Result] String
x : Eff [Result; IO] String
x : Eff [Random] String;

() = format();

(x : Nat 1) => x + x;

Socket : {
  connect : () -> $Socket;
  close : $Socket -> ();
};
() => (
  x = Socket.connect();
  Socket.close(x);
);

x => y => x;
x => y => y;

r0 : Linear
r1 : Linear

(three, r1) = add(r0, r1);

Array : {
  $Array : (A : Type) -> Type;

  make : () -> $Array Int;
  get : {A} -> (i : Nat, arr : Array A) -> (Array A, Option A);

  Read_only_array : _;

  split : (i : Nat, arr : Array A) -> (List (Read_only_array A i arr))
  merge : (l : List (Read_only_array A i arr)) -> Array A;
} = _;

f = arr0 => (
  (arr1, x) = Array.get(0, arr0);
  (arr2, y) = Array.get(1, arr1);

)
find : () -> Eff [Database] (List User);

integration()

@debug(find())

Unification

(A : _) -> _B[close +3] === (A : _) -> \-1
(A : _) -> _B[close +3] === (A : _) -> \-1
_B === \-1[open \+3]


(A : Type) -> A\+2 === (A : Type) -> A\+2


(A : _) -> (_C ((B : _) -> _C))[close +2] === (A : _) -> (_D ((B : _) -> \-2))
(_C ((B : _) -> _C))[close +2] === (_D ((B : _) -> \-2))
((B : _) -> _C)[close +2] === (B : _) -> \-2
_C[lift (close +2)] === \-2
_C === \-2[lift (open \+2)]
_C === \-1

_C[shift] === \-2
_C === \-2[lower]

_A[lift s] === \-2
_A === \-2[lift (not s)]

_A[lift (close +n)] === \-2
_A === \-2[lift (open \+n)]
\-2[lift (open \+n)][lift (close +n)] === \-2
\+n[lift (close +n)] === \-2
\-2 === \-2

_A[lift (open +n)] === \+n
_A === \+n[lift (close +n)]
\+n[lift (close +n)][lift (open +n)] === \+n[lift (close +n)]
\-2[lift (open +n)] === \+n[lift (close +n)]
\-2[lift (open +n)] === \+n[lift (close +n)]


_A[lift (close +n)] === \+n

_A[shift] === \-2
_A[shift] === \-2

_A === \-2[1 . id]


(A : Type) -> _A
l := t

expected : ((x : \+1[id]) -> \+1[close +3])[id]
received : ((_x0 : \+3[id]) -> \+3[id])[id][lift id][open \+3][+3 := \+1][id]

_A[close \+2][open \+3] === +2
_A === +2
_A[close \+2][open \+3] === +2

_A === -1

_A === +1[open +2]

_A[x := N] === x
x === x


_A[+2] ===

x[x := N] === x

(λλ_A[lift (1 1)] === λλ2)
(λ_A[lift (1 1)] === λ2)
(_A[lift (1 1)] === 2)

(x => _A) N === y


_A[x := N] === x

Γ,Δ1 |- A    Γ,Δ2 |- B
----------------------
    Γ |- A === B


_A[open +2][close +2] = -1
_A = -1[open +2][close +2]

Γ |- e : A  Γ |- r[x := e] : B
------------------------------
    Γ |- x = e; r : B

(Id = (A : Type) => A; )

m.n
_::n(m)

m.n a b
_::n

Magic Dot

Nat = (A : Type) -> (z : A) -> (s : (x : A) -> A) -> A;
(zero : Nat) = A => z => s => z;
(succ : (n : Nat) -> Nat) = n => A => z => s => s (n A z s);
(add : (n : Nat) -> (m : Nat) -> Nat) = n => m => n Nat m succ;
(mul : (n : Nat, m : Nat) -> Nat) = n => m => n Nat zero (add m);
one = succ zero;
two = succ one;
four = mul two two;
eight = mul two four;
sixteen = mul two eight;
byte = mul sixteen sixteen;
byte String "zero" (_ => @native("debug")("hello"))


x.f === _::f(x)
x.f (1, 2) === _::f(x)(1, 2)


add = (!n : Nat, !m : Nat) => n + m;
id = {A} => (x : A) => x;

add = (!n : Nat, !m : Nat, log : Option Bool) => n + m;

x = add (n = 1, m = 2);

(1, 2) : (_A : Nat, _B : Nat);

(_A : Nat, _B : Nat) === (n : Nat, m : Nat)

(_A : Nat, _B : Nat) === (!n : Nat, !m : Nat)

(x = 1, y = 2) : (x : Nat, y : Nat);


Int : {
  @Int : Type;
  show : (i : @Int) -> () -> String;
};

ind_bool : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
ind_bool : (b : Bool (i + 1)) ->
  (P : Bool i -> Type) -> P true -> P false -> P (lower b);

Consistency = Soundness + Strong Normalization;

(Type 0 : Type 1)
(Type n : Type (n + 1))

id = (A : Type 1) => (x : A) => x;

id (Type 1)


ind_bool : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b = _;


Γ, x : @self(x). T |- T : Type
------------------------------
Γ |- @self(x). T : Type


Γ, x : @self(x). T |- M : T[x := @fix(x). M]
--------------------------------------------
Γ |- @fix(x). M : @self(x). T


Γ |- M : @self(x). T
--------------------------
Γ |- @unroll M : T[x := M]

TCO Nat

two = z => s => s (s z);
two = z => s => s z (x => s x);
three = z => s => s z (x => s x s)

Prevent Currying

id = (x : 'A) => x;

((x : 'A) -> 'A)

id : (x : 'A) -> 'A;
sum : (x : Int, y : Int) -> Int;

sum : (f : (x : Int, y : Int)) -> Int;

id (1);
sum 1 2;

sum (1, 2);
(x = (1, 2); sum(...x))
(sum((1, 2)))

(x, y) = id(_ = (1, 2));

(x, y) =>

ind : (b : Bool, P : Nat -> Type) -> (x : P true, y : P false) -> P b;
sum : (x : Int) -> (y : Int) -> Int;

sum 1 _


?sum 1 _
y => ?sum 1 _

id(1, 2) : (1, 2)


add a b = c;

// named return
(x : Int) -> (x : Int)

Nominal

(Bool : Type) -> (true : Bool) -> (false : Bool) ->w

(Bool : Type) & {
  true : Bool;
  false : Bool;
  case : {A} -> (pred : Bool, then : A, else : A) -> A;

} = _;

add 1 ~> add 1
add 1 2 ~> 3

Γ |- A : Type
--------------------------
Γ |- @frozen(A) : Type

Γ |- M : A
--------------------------
Γ |- @freeze M : @frozen A

Γ |- M : @frozen A
--------------------
Γ |- @unfreeze M : A

---------------------------
@unfreeze (@frozen M) === M

T =
  (R : Type) ->
  ((A : Type) ->
    (x : A) ->
    (to_string : A -> String) ->
  R) -> R;

M : T = _;

to_string : ((A : Type) -> M ) -> String;

M : {
  Nat : Type;
  one : Nat;
  to_int : Nat -> Int
} = @nominal(key => (
  Nat = @frozen(key, Int);
  one = @freeze(key, 1);
  to_int = x => @unfreeze(key, x);
));

T = @nominal(key => (
  Nat = @frozen(key, Int);
  one = @freeze(key, 1);
)).Nat;

M.one

Primitives

External

Linear Machine

(2 x : Int) => x + x

Escape

call v f = f v
(A : Type) -> A


mono = w => x => y => (id => w (k x) (k y)) (x => x);
(a : _A\+1) => (A : Type) => (b : _B\+2) =>




(x => x) 1

((2 x : _A & _B) => (x : _A) + (x : _B))

(x0 : Int) => (x1 : Int) => x0 + x1


Nat (G : Grade) = (A : Type) -> (1 z : A) -> (G s : (1 A) -> A) -> A;
(x : Nat) => x Nat zero (acc => acc);

|- Type : Type


Γ |- e : A : Type

(('G + 1) x : @rec T. ('G x: T) -> _) => x x
(x : @rec T. (x : T) -> _) => x x

((x : A) => x) : ((x : A) -> A) : Type



Γ |- e : A : Type

x = Type;



-----------------
ctx, x : A |- x : A


ctx |- func : A -> B    ctx |- arg : A
----------------------------------
ctx |- func arg : B

-----------------------------------------
ctx |- (x => body) arg === body[x := arg]


----------------------------------------
ctx | setState |- setState(false) === ()


My_button = (label : String) => <Button>{label}</Button>;


My_button label

My_button =
  ctx |- label : String
  --------------------------------
  ctx |- <Button>{label}</Button>


ctx |- My_button : String -> DOM    ctx |- label : String
---------------------------------------------------------
ctx |- My_button label === <Button>{label}</Button>: DOM


ctx |- label : String
-------------------------------
ctx |- <Button>{label}</Button>


My_button = (label : String) => <Button>{label}</Button>;

(A : Type) -> _A -> _B === (A : Type) -> _A -> _B

(A : Type) -> _A[close +2] === (A : Type) -> A\-1


_A[open \+2 \+2][close +2] === -1



_A[close +2] === +2


+2 |- (λ_A[close +1]) +2 === _B
+2 |- _A[close +1][open +2] === _B
+2 |- _A[close +1] === _B[close +2]
+2 |- _A === _B[close +2][open +1]

+2 |- _A === _B[close +2][open +1]


+2 |- (λ_A) +2 === _B
+2 |- _A[open +2] === _B
+2 |- _A === _B[close +2]



_B[close +2][open +1] === +2
_B === +2[open +2]

_B[close +1] === +2[open +2]

_B[close +2] === +2


_B[close +2] === +2
_B[open +2] === +2

[y] |- (x => _A) y === _B
[y] |- _A[x := y] === _B
[y] |- _A === _B[y := x]



unify = a => b => (k => (_ = k a); k b) (x => x);

P => y => z => (f : (x : _) -> P _A) => (g : P _B) =>
  unify (f y : P (_A[x := y])) g

(P (_A[x := y]) : P _B)



a : P (_B[y := x])
a : P y

_B[y := x] == y

_A[x := y] == _B

_A[x := y] == _B[y := x]


P => y => z => (f : (x : _) -> P _A) => (
  _ : P _B = (f y : P (_A[x := y]));
  // _A === _B[y := x]
  (f z : P y)
);

P => y => z => (f : (x : _) -> P _A) => (
  _ : P _B = (f y : (P _A)[x := y]);
  // _A === _B[y := x]
  (f z : P y)
);

(P _A)[x := y] === P y

P (_B[y := x][x := z]) === P y

_B[y := x][x := z] === y

// I think this cannot happen
P => y => z => (f : (x : _) -> P _A) => (
  _ : P _B = (f y : P (_A[x := y]));
  // _A === _B[y := x]
  (f z : P y)
);
_B[y := x] == y


_B[y := x] == y


_B[close +2] === +2


_A[x := y] == y
_A[x := y][y := x] == y[y := x]
_A == x


l |- _A == r |- _B


_A := _C[!r]
_B := _C[!l]


l |- _C[!r] == r |- _C[!l]
l . !r |- _C == r . !l |- _C

_C == _C

_C[l][!r] == _C[r][!l]

_C[l][l] == _C[r][r]
_C[l][!r][l] == _C[r]

_C

x[close +3][open +3][close +3]

Γ, x : Int |- xy : Int

(f => y => ) (x => x)

((x => x) y)[y := z]
(x => x[y := z]) y[y := z]
(x => x) z

(x = y; x)[y := z]
(x = y[y := z]; x[y := z])
(x = z; x)


(x = y; x[y := z])
(x = y; x[y := z])
x[y := z][x := y]

(x = y; equal x y)
(equal x y)[x := y]

x === y

one = s => z => s z;
two = s2 => s1 => z => s2 (s1 z);

Nat 'n = (A : Type) -> ('n f : A -> A) -> A -> A;

Bool (n : Grade) =
  (A : Type) -> (B : Type) -> (A -> B) -> A -> B

true = x => y => x y;
false = x => y => y;

(A : Type)

Type n


(x : Int 'n) -> (y : Int 'n) -> Int 'n

Nat =
  union
    (case "z" end)
    (case "s" (cell self) end)
  close;

Bool =
  | (tag : #true)
  | (tag : #false);

Either A B =
  | (tag : "left", payload : A)
  | (tag : "right", payload : B);

| ("left", a) => _
| ("right", b) => _

Either A B = (tag : Bool, payload : tag Type A B);

| (true, a) => _
| (false, b) => _

Either A B =
  | True(payload : A)
  | False(payload : B);

| True(a) =>
| False(b) => _

data%Bool =
  | true
  | false;

x = #true;

Nat =
  | (tag : "z")
  | (tag : "s", pred : Nat);

"z" : Nat
("s", ("z", ()))
Nat =
  | Z | S (n : Nat);

1 + 2 : Int _a
1 : Int _n
((A : Type 0) => (x : A 1) => x) : Type 15;

Teika Schema

NONCE, auto retry
VERSION
TRANSACTION
LOGIN
PERMISSION
SECURITY


WEBSOCKET
STATEFUL APIs

Teika Database

User and Post
Both indexed by User.id

Teika Workers

{

}

Teika System

Workers + Database

storage@User = {
  @index id : @increment Nat;
  name : String;
};

User : {
  insert : _ -[DB.write "user"]> ();
  find_by_id : _ -[DB.read "user.id"]> ();
} = _;

@Routes = [
  POST "/users" =
    { name : String; } => User.insert { name = name; };
  GET "/users/:id" =
    { id : Nat; } => User.find_by_id id;
  GET "/users" =
    () => User.list ();
];

test@routes = [
  POST "/users" { name = "EduardoRFS"; }
    expected { id = 0; name = "EduardoRFS" };
  GET "/users/0"
    expected { id = 0; name = "EduardoRFS" };
];


((x : Nat) -> f x == g x)

(x : Nat) -> Nat

\forall x : Nat. Nat
∀x : Nat. Nat

ind : ∀b.P. P true -> P false -> P b;

ind : (b : _) -> (P : _) -> P true -> P false -> P b;

x => x

\lambda x. x
λx -> x

Inductive Linear : Context -> Term -> Type :=
  | L_var var : Linear [var] (T_var var)
  | L_lam {lam_ctx} param
    {body_term} (body : Linear (param :: lam_ctx) body_term)
    (param_not_free_in_lam_ctx : free_in_ctx param lam_ctx = false)
    : Linear lam_ctx (T_lam param body_term)
  | L_app {lam_ctx lam_term} (lam : Linear lam_ctx lam_term)
    {arg_ctx arg_term} (arg : Linear arg_ctx arg_term)
    : Linear (append lam_ctx arg_ctx) (T_app lam_term arg_term)

x ⊢ x


Γ, x ⊢ M -> not (free x Γ) -> Γ ⊢ x. M

First-class Grades

Fix n = (Fix 1, (f : Fix 1) -[1]> Unit);
(f : Fix 1) => (
  (x, k) = f;
  k x;
)


Fix (G + 1) = (x : Fix G) -[1]> Unit;
(x : Fix 1) => (
  x x
)

Nat = (G : Grade, (A : Type) -> (1 z : A) -> (G s : A -> A) -> A);

f = (G : Grade) => Int G

T = Int 1;

((A : Type) -> A);

Type 0 : (G : Grade) -> Type 1 G




Γ |- n : Grade  Γ |- A : Type
-----------------------------
Γ, x $ n : A

Type : Type $ 0;

Γ |- A : Type  Γ |- n : Grade
-----------------------------
Γ |- M : A $ n

Γ, x : A $ n |- B : Type $ 0
------------------------------------
Γ |- ((x : A $ n) -> B $ m) : Type $ 0

Γ, x : A $ n |- M : B $ m
--------------------------------------------------
Γ |- (x : A $ n) => M : ((x : A $ n) -> B $ m) $ k

Γ |- M : ((x : A $ m) -> B $ n) $ 1  Γ |- N : $ n
--------------------------------------------------
Γ |- M N : ((x : A $ n) -> B $ m) $ k

(x : A $ 1) => x : A
Type $ 0 : Type

(x : Socket$) => _;


Id
  : (A : Type $ 0) => Type $ 0;
  = (A : Type $ 0) => A;
Never = (A : Type) ->
id = (A $ 0 : Type) => (x $ G : A) => x
id = ({A} => (x $ 1 : A) => x) $ 15;

A $ G -> A $ G
id
  : (A : Type $ 0) -> (x : A $ 'X) -> (A $ 'X) $ _G
  = (A : Type) => (x : A) => x;

(x : Int $ 5) => (
  incr () = x + 1;

  incr : () -> (Int $ _X) $ _Y where _X * _Y = 5

  // but, this seems as powerful
  incr : () -> (Int $ 1) $ 5
  // and more general than, but maybe this could put it back
  incr : () -> (Int $ 5) $ 1
);
Nat = (G : Grade, (A $ 0 : Type) -> ($ 1 : A) -> ($ G : ($ 1 : A) -> A) -> A);


Bool : Type;
true : Bool;
false : Bool;

Bool = b @-> (P : Bool $ 0 -> Type $ 0) ->
  P true $ @b (_ => Grade) 1 0 ->
  P false $ @b (_ => Grade) 0 1 -> P b $ 1;
true = P => x => y => x;
false = P => x => y => y;

dup (b : Bool $ 1) : Bool $ 2 =
  b _ true false;

// without Grade : Type
Bool : Type;
true : Bool;
false : Bool;

Bool = b @-> (P : Bool $ 0 -> Type $ 0) ->
  @b (_ => Type $ 0) (P true $ 1) (P true $ 0) ->
  @b (_ => Type $ 0) (P false $ 0) (P false $ 1) -> P b $ 1;
true = P => x => y => x;
false = P => x => y => y;

dup (b : Bool $ 1) : Bool $ 2 =
  b _ true false;

// erasable only
Bool : Type;
true : Bool 'G;
false : Bool 'G;


Bool = b @-> (P : Bool $ 0 -> Type $ 0) ->
  P true $ @b (_ => Grade) 1 0 ->
  P false $ @b (_ => Grade) 0 1 -> P b;
true = P => x => y => x;
false = P => x => y => y;

dup (b : Bool $ 1) : Bool $ 2 =
  b _ true false;

//
Unit = (0 A : Type) -> A -> A;
unit : Unit = A => x => x;

Bool_0 = (0 K : Type) -> ((0 A : Type) -> A -> K) -> K;
true : Bool_0 = K => k => k Unit unit;
false : Bool_0 = K => k => k Unit unit;

// closed
Closed A = <G>A $ G;

Bool = (A : Type) -> Closed A -> Closed A -> A;
true : Closed Bool = <G>(A => x => y => (_ = y<0>; x)) $ G;
false : Closed Bool = <G>(A => x => y => (_ = x<0>; y)) $ G;

dup (b : Bool $ 1) : Closed Bool =
  b (Closed Bool) true false;



case : (b : Bool_0) -> (A : Type) -> (<G>(A $ G) $ 1) ->

// inductive version
Bool_0 b = (
  (G_true, G_false) = b;
  (P : Bool_B -> Type) -> P true_b $ G_true -> P false $ G_false -> P b $ 1
);
true_0 : Bool_0 true_b = P => x => y => x;
false_0 : Bool_0 false_b = P => x => y => y;

// church version
Bool_B = (Grade, Grade);
true_b : Bool_B = (1, 0);
false_b : Bool_B = (0, 1);

Bool_0 = (
  G_true : Grade, G_false : Grade,
  (A : Type) -> A $ G_true -> A $ G_false -> A $ 1
);
true_0 : Bool_0 = (1, 0, A => x => y => x);
false_0 : Bool_0 = (0, 1, A => x => y => x);

//


Bool : Type;
true : Bool;
false : Bool;

Bool = b @-> (P : Bool $ 0 -> Type $ 0) ->
  @b (_ => Type $ 0) (P true $ 1) (P true $ 0) ->
  @b (_ => Type $ 0) (P false $ 0) (P false $ 1) -> P b $ 1;
true = P => x => y => x;
false = P => x => y => y;

dup (b : Bool $ 1) : Bool $ 2 =
  b _ true false;
@Bool =
  b @->
  (P : Bool $ 0 -> Type $ 0) ->
  P (b @=> P => (x : P b $ 1) => (y : P b $ 0) => x) $ b (_ => Grade) 1 0 ->
  P (b @=> P => (x : _ $ 0) => (y : P b $ 1) => x) $ b (_ => Grade) 0 1 ->
  P b $ 1;
true :
dup : ()
expected :
  P (b @=> P => (x : P b $ 1) => (y : P b $ 0) => x) $ 1 ->
  P (b @=> P => (x : _ $ 0) => (y : P b $ 1) => x) $ 0 ->
  P (b @=> P => (x : P b $ 1) => (y : P b $ 0) => x) $ 1
received :
  P (b @=> P => (x : P b $ 1) => (y : P b $ 0) => x) $ 1 ->
  P (b @=> P => (x : _ $ 0) => (y : P b $ 1) => x) $ 0 ->
  P (b @=> P => (x : P b $ 1) => (y : P b $ 0) => x) $ 1

Monolith Graded CoC

Γ |- n $ 0 : Grade  Γ |- A $ 0 : Type
------------------------------------- // Rule
Γ |- t $ n : A $ 0

------------------------- // Type
() |- Type $ 0 : Type

----------------------- // Grade
() |- Grade $ 0 : Type

Γ $ 0 |- A : Type
----------------------------- // Var
Γ $ 0, x $ 1 : A |- x $ 1 : A

Γ |- A $ 0 : Type  Γ |- r $ 0 : Grade
Γ, x $ p : A |- B $ 0 : Type
------------------------------------- // Forall
Γ |- (x $ p : A) -(r)> B $ 0 : Type

Γ, x $ p : A |- t $ r : B
-------------------------------------------------- // Lambda
Γ |- (x $ p : A) =(r)> t $ 1 : (x $ p : A) -(r)> B

Γ |- f $ 1 : (x $ p : A) -(r)> B  ∆ |- a $ p : A
------------------------------------------------ // Apply
Γ, ∆ |- f a $ r : B[x := a]

Γ |- t $ r : A
---------------------- // Multiply
Γ $ n |- t $ r * n : A



Γ |- f $ 1 : (x $ p : A) -(r)> B  ∆ |- a $ p : A
------------------------------------------------ // Apply
Γ, ∆ |- f a $ r : B[x := a]


((x $ 1) =(0)> (x $ 1) x)


(x $ 1) => (
  f = (() => x $ 1);
  (f () $ 0)
)

f = (() => x) $ 1;


() -> (x $ 0) @=> x

// consumes 4 nat and produces 2 nat
(x $ 4 : Nat) -(2)> Nat

// closed terms can produce G
(G : Grade) =(G)> (x $ 1 : Nat) =(1)> x;

Formal Linear

Teika Syntax

Pat =
  | x // var
  | P : A // annot
  | !P // strict
  // TODO: optional
  | <P> // implicit
  | (P, ...) // tuple
  | { P; ... }// module

Term =
  | x // var
  // TODO: all patterns?
  | (x : A) -> B // explicit forall
  | <P>B // implicit forall
  | P => M // lambda
  | M N // explicit apply
  | M<N> // implicit apply
  // TODO: explain strict, like annot
  | !M // strict
  // TODO: optional / currying?
  | (x : A, ...) // exists
  | (P = M, ...) // tuple
  | { P : M; ... } // signature
  | { P = M; ... } // module


(x : T).a
T::a(x);

(A : Type <: )

(<A>, x) = (a : (<A>, x : A));
<S : Show> =


(b, <P>, x : P true, y : P false) -> P b
∀b.P. P true → P false → P b
(b : _) -> (P : _) -> P true -> P true -> P b

Show = Σ(t : Type, x : T)
// lambda

// apply
M N
// strict apply
!M N
// curried apply
?M N


Fix = (x : FixX) -> ()
FixX = (G : Grade) -> ((x1 : Fix) -> (x : FixX) -> );
fix : Fix = x => (
  x
)
(G : Grade) ->

Linear + Erasable System F

(Grade Kind) GK ::== | + | GK -> GK
(Grade)    G, H ::== | g | 0 | 1| λx : GK. G | G H | ∀g. G
(Type)     T, U ::== | A | T -> U          | ∀A. T       | T $ G   | ∀g. T
(Term)     M, N ::== | x | λx : T. M | M N | ΛA. M | M T | [M $ G] | ΛG. M | M G
(Context)  Γ, Δ ::== | • | Γ, x : T        | Γ, A        | Γ, g


λx : A.

Nat_GK = + -> (+ -> +) -> +;
zero_gk : Nat_GK = λz. λs. z.
succ_gk : Nat_GK -> Nat_GK = λn. λz. λs. s (n z s).

Λg. ΛA. λx : A $ g. x
Λg : Nat_GK. ΛA. λz : A. λs : A $ g. x

∀g . g

(λx : . x) : * -> *

// only weak existentials, can be done through lambdas
Bool === ∃l.r.A. A $ l -> A $ r -> A;
// erasables can be weakened
true : Bool === pack 1. pack 0. λx. λy. x;
false : Bool === pack 0. pack 1. λx. λy. y;

dup : Bool -> (Bool * Bool) === λb.
  unpack (l, (r, b)) = b in
  // closed terms can satisfy any grade
  b (Bool * Bool) [(true, true) $ l] [(false, false) $ r]



Closed A === ∀g. (A $ G);
Nat === ∀A. A -> Closed (A -> A) -> A;
zero : Nat === ΛA. λz. λs. (_ = s 0; z);
one : Nat === ΛA. λz. λs. s 1

Bool === ∀A. Closed A -> Closed A -> A;
// erasables can be weakened
true : Bool === ΛA. λx. λy. (_ = y 0; x);
false : Bool === ΛA. λx. λy. (_ = x 0; y);

dup : Bool -> Closed (Bool * Bool) ===
  // closed terms can satisfy any grade
  λb. b (Bool * Bool) (Λl. [(true, true) $ l]) (Λr. [(false, false) $ r])

Context Dependency

Term =
  | Context
  | •
  | Γ, (x : A)
  | M[Γ]
  | Type
  | x
  | ∀(x : A). B
  | λ(x : A). M
  | M N;

• |- Γ : Context  Γ |- A : Type
-------------------------------
Γ |- M : A

----------------
• |- Type : Type

-------------------
• |- Context : Type

----------------
• |- ∅ : Context

Δ |- Γ : Context  Γ |- A : Type
-------------------------------
Δ |- Γ, (x : A) : Context

Γ |- Δ : Context  Γ ∘ Δ |- M : A
--------------------------------
Γ |- M[Δ] : A

• |- Γ x : A
------------
Γ |- x : A

• |- Γ 0 == A
-------------
Γ |- 0 : A

0 = (x : Type) => x

Γ ((x : Type) => x) == A

((x : Type) => x) A == A

• |- Γ 0 == (x : A) -> B  • |- Γ 1 == A
---------------------------------------
Γ |- 0 1 : B[x := A]

• |- Γ 1 == A
-------------
Γ |- 1 : A

Nat = _;

true = x => k => k (x => x) x;
false = x => k => k x ();

weak ctx v = ctx (S v);
xchg ctx v = ctx (S v)
drop ctx =


[1; 2; 3]
[2; 1; 3]
[(λx y k.k x y); 2; 1; 3]
[(λy k.k 2 y); 1; 3]
[(λk.k 2 1); 3]
[3; (λk.k 2 1);]

x => k =>
true = λ(λ0);
false = λλ0;

xchg ctx v =
  ctx
  | ctx, x =>
    (ctx
    | ctx, y => Some (ctx, y, x)
    | ctx => None)
  | ctx => None;

xchg ctx v =
  ctx
  | ctx, x =>
    (ctx
    | ctx, y => Some (ctx, y, x)
    | ctx => None)
  | ctx => None;

apply = x => y => (x y)[xchg];

Nat_0 = Type -> (Type -> Type) -> Type;
one_0 = x => s => s x;

Nat_1 n0 =

Context = (A : Type) -> A -> (Type -> A -> A) -> A;
empty : Context = A => acc => f => acc;
cons T ctx = A => acc => f => f T (ctx acc f);

rev ctx = ctx Context(A => Γ => A . Γ);

empty = (Type, None);

T | Γ |- Δ : Context  Δ |- T : A
--------------------------------
T | Γ |- M[Δ] : A

(T, x : )
apply = (x : Type -> Type) => (y : Type) => (x y)[x => y => k => k y x];

apply = x => (x y)[x => k => k {} x];

ctx 0 = A;
ctx 1 = B;

xchg ctx 1 = ctx 0
xchg ctx 0 = ctx 1


Nat = Type -> (Type -> (Type -> Type) -> Type) -> (Type -> Type) -> Type;
zero = z => s => k => k z;
succ = n => z => s => k => s (r => n )
empty v = None
append ctx A v =
  v (Some A) (x => ctx (z => ))
()

(b : Bool) => M[b Context (, (x : Bool)) (, (y : Bool))]

Dependent substitutions

// first-class binders?
Term =
  | Subst
  | [xchg]
  | [x : A]
  | M[Δ]
  | Type
  | x
  | ∀(x : A). B
  | λ(x : A). M
  | M N;

Γ |- A : Type
-------------
Γ |- M : A

----------------
• |- Type : Type

-----------------
• |- Subst : Type

--------------
• |- xchg : Subst

Γ |- A : Type
--------------------
Γ |- [x : A] : Subst

--------------
• |- xchg : Subst

Γ |- A : Type
-----------------------
Γ |- M[xchg] : Γ, x : A

Γ |- Δ : Subst  Δ Γ |- M : A
-----------------------------
Γ |- M[Δ] : A

// reflections

apply = x => y => (x y)[xchg];
apply = (x y)[y][x]

apply = x[y][x] y[y][x]

(b : Bool) =>
  M[b Subst [x : Bool] [y : Bool]][b Subst [y : Bool] [x : Bool]]

M[b Context [x : Bool] [y : Bool]]
b _ ((x : Bool) => M) ((y : Bool) => M)

M[b Context [x : Bool] [x : Int]]

b _ ((x : Bool) => M) ((x : Int) => M)


M[x : A]

Ordered Lambda Calculus

Closed A = <G>A $ G;

swap = <A> => (x : A) => (y : A) =>
  <K> => (k : A -> A -> K) : K => k y x;
noop = <A> => (x : A) => (y : A) =>
  <K> => (k : A -> A -> K) : K => swap y x (x => y => swap x y k);

Bool =
  <A> -> Closed A -> Closed A -> Closed A;
true : Closed Bool =
  <G> (<A> => x => y => noop y x (x => y => ((_ : A $ 0) => x) (y<0>))) $ G;
false : Closed Bool =
  <G> (<A> => x => y => swap y x (y => x => ((_ : A $ 0) => y) (x<0>))) $ G;

dup (b : Bool) : Closed Bool = b Bool true false;

[x; y] |- term
[y; x] |- (y => x => term) y x

[a; b; x; c; d] |- term
[x; a; b; c; d] |-
(c => d => (d => c => x => b => a => term) d c x a b) c d


(d => c => x => b => a => term) d c


(d => c => x => b => a => term)
(c => d => (d => c => x => b => a => term)) x a b c d
x => y => y x

x => y => x y

x => y => (y => x => x y) y x

[x; y] body
x => (y => body)

((f lam a) b) c
f lam a b c
(x => y => k x y)


x ∈ Γ  x ∉ Δ
------------
Γ, Δ

------
x |- x

Γ, x |- M
----------
Γ |- λx. M

Γ |- M  Δ |- N
--------------
Γ, Δ |- M N


//
------
l |- 0

l |- x
----------------
l + 1 |- (1 + x)

l + 1 |- M
----------
l |- λ.M

l |- M  r |- N
--------------
Γ, Δ |- M N

λx.λx.x x

λx.x x


G ::== | g | 0 | S g | ∞


------
1 |- 0

n |- n
--------------
1 + n |- n

1 + Γ |- M
----------
Γ |- λM

Γ |- M  Γ + Δ |- N
------------------
Γ + Δ |- M N

λ λ (λ0) 1 2

Γ |- M  Δ |- N
--------------
Γ, Δ |- M N


<A>(x : A) => A

(x => M)(N)
M[x := N]


(x => x x) (x => x x)
(x x)[x := x => x x]
(x => x x) (x => x x)

(x => x x)(x => x x)
(x x)[x := x => x x]
(x => x x) (x => x x)

Promise<[A]>

0 0

λ 0 1

M |-
--------------------
M :: N :: [] |- @ :

Γ, x |- M
----------
Γ |- λx. M

Γ |- M  Δ |- N
--------------
Γ, Δ |- M N

CPSify

Term =
  | Type

  | x
  | (x : A) -> B
  | (x : A) => M
  | M N
  | x @-> T
  | x @=> M
  | @M;

Value =
  | Grade
  | Type
  | x
  | (x : A) -> B
  | (x : A) => M;
Term =
  | ...Value
  | M V;


[f => x => m (x => f x)]
f => x => m (f x)

Id = <A>(x : A) -> A;
Bool = <A>(x : A, y : A) -> A;
not : (b : Bool) -> Bool = _;
if : (b : Bool) -> Bool = _;

call_if (if : (b : Bool) -> Bool) b = if b 1 0;

f : (id : <A>(x : A) -> A) -> Int
f id = id 1;

f : (id : (x : Int) -> Int) -> Int
f id = id 1;

left_or_right :  String -> String -> String -> String
left_or_right l r = (
  b = String.equal l r;
  b "abc";
);
left_or_right l r = (
  b = String.equal l r;
  b (y => "abc") (y => y);
)

b := (b_ptr, 0, null, null)
b := (b_ptr, 1, x,    null)

rec@fold f acc n =
  n
  | 0 => acc
  | S p => fold f (f acc) p;

mul = n => m => fold (acc => add acc m) 0 n;
mul = n => m =>
  (rec fold f acc n =>
  n
  | 0 => acc
  | S p => fold f (add acc m) p
  ) 0 n;

Dynamic Range

TypeScript / Rust ->
Java / C / C++ / OCaml ->
Python / Go / Clojure / Elixir ->
Swift / Haskell / PHP / Ruby

Rust is affine / linear
Rust uses result for everything
TypeScript IO is fully tracked




const id = (x : Nat) => x;
const id = <A>(x : A) => x;
type Id<A> = A;
type T<B> = B extends true ? number : string;

id = (x : Nat) => x;
id = (A : Type) => (x : A) => x;
Id = (A : Type) => A;
T = (B : Bool) => b | true => Nat | false => String;

module type S = sig
  type t
  val x : t
end
type t = { x : int; }
type fcm = (module S)
type 'a obj = object val x : int end as 'a

S = {
  T : Type;
  x : T
};
t = { x : Int; };
fcm = S;
obj = R => ({ x : Int; ...R; })


if_b_then_int_else_string
  : (b : Bool) -> (x : b | true => Int | false => String) => b | true => Int | false => String
  = (b : Bool) => (x : b | true => Int | false => String) => x;


if_b_then_int_else_string = <A extends bool>(b : A extends true ? number : string, x : A) => x


f = (s : String & JSON.is_valid s == true) => s;

Color =
  | Red
  | Green
  | Blue;

f = (color : Color & color != Red) => _;
make = (n : Int & n >= 0 || n == -1) => n;


id = (A : Type) => (x : A) => (
  () = console.log(x);
  x
);

incr = (x : id Type Int) => x + 1;

incr = (x : Int) => x + 1;

main : IO ()
main = print "Hello World"

print : World -> String -> World;

main : World -> World
main world0 = (
  world1 = print world0 "Hello World";
  world2 = print world0 "Wrong";
  world2
)

Socket : {
  send : (sock : Socket, msg : String) -> Socket;
  close : (sock : Socket) -> ();
};

f = (s : Socket) -> (
  s1 = send(s, "a");
  close(s1);
)

double = (x : Nat $ 2) => x + x;
double = x => x + x;

id = (A : Type $ 0) => (x : A $ 1) => x;
dup = (x : Nat $ 2) => (x : Nat, x : Nat);


CoC
+ Self Types
+ Graded
+ Inference


read = (file : String) -> Eff [Read] (String);

read "hello.txt"

id = (x : Nat) => (
  () = @debug(x);
  x + 1
);
() = Fuzz.nat(x => x == id x);


Nat => number | bigint
Int => number | bigint


Int32 => number | 0
Int64 => [number, number] | bigint


id = (A : Type) => (x : A) => x
x = id 1;
y = id "a";


x = id 1;
y = id "a";


call_id = (id : (A : Type) -> (x : A) -> A) => id(1);

data@Option<A> =
  | Some(content : A)
  | None;

apply = x => y => (y => x => x y) x y;


ML = f -> f

read : (world : World, file : String) -> Result (World, String) Error;

read : (world : World, file : String) -[Error]> (World, String);
read : (file : String) -[IO]> String;

main : () -[IO]> ()
main () = (
  file = read("tuturu.txt");
  print(file);
);

List.map (x =>
  x.? > 0
  | true => Ok (x + 1)
  | false => Error "bad"
)

List.map (x =>
  x > 0
  | true => x + 1
  | false => throw (Error "bad")
)

main : Eff [IO; Error] ()

main : World -> World
main world = (
  file = read("tuturu.txt");
  print(file);
);




Term =
  | Type
  | (x : A) -> B
  | (x : A) => M
  | M N
  | x @-> T
  | x @=> M
  | @M;

Term =
  | Type
  | (x : A $ G) -> B
  | (x : A $ G) => M
  | M N
  | x @-> T
  | x @=> M
  | @M;

Unit = Unit @=> I =>
  u @-> (P : (u : Unit) -> Type) -> (x : I P (u @=> P => x => x)) -> I P u;


Fix = (x : Fix $ 0) -> Type;

f = ((x : Fix $ 0) => x x);

f = ((x : Fix $ 0) => x x);



False = False @=> f @->
  (P : ((f : False $ 0) -> Type) $ 0) -> P
(x : @f f) => _;





False = False @=>
  f @-> (P : ((f : False $ 0) -> Type) $ 0) -> P f

Γ |- M : (x : A $ n) -> B $ 1  Δ |- N : A $ n
---------------------------------------------
Γ, Δ |- M N $ 1

Fix = (x : Fix $ 1) -> Type;

T : (T $ 0, 1) @-> Type = T @=> @T;


x = (A : Type $ 0, 2) -> Type;
y = (A : Type $ 0, 2) => (x : A) -> A;

y = (A : Type $ 0, 2) => (x : A) -> A;

T : (T $ 0, 1) @-> (A : Type) -> Type = T @=> @T;

@(T @=> @T) === @(T @=> @T)

False = (False : Type $ 0) @=>
  f @-> (P : ((f : False $ 0) -> Type) $ 0) -> P f

T_x : (f $ 0, 1) @-(0)> (A : Type) -> A;

f : T_x = f @=> @f;
x = @f : (A : Type) -> A $ 0;


Fix = (x $ 0, 0 : Fix) -(0, 0)> ();
fix : Fix = (x $ 0, 0 : Fix) =(0, 0)> x x;
Fix = (x : Fix $ 0, 0) -> ();

Id = (A : Type $ 0) =(0)> A;

((x : Id Nat) => x);

False @-(0)> Type;

Unit = Unit @=(1)> I =>
  u @-(1)> (P $ 2 : (u $ 1 : @Unit I) -> Type) -(1)>
    (unit $ 1 : I P (u @=> P => x => x)) -(1)> I P u;


T_False = False @-(2)> (f $ 1 : f @-(1)> @False f) -(1)> Type;
False $ _G : T_False = False @=(2)> f =>
  (P : (G : Grade) (f $ 1 : f @-(1)> @False f) -> Type) -(1)> P f;

T_Unit = Unit @-(_)>
  (I : I @-> ) -(1)> Type;
Unit : T_Unit = Unit @=(_)> I =>
  u @-(_)> (P $ 2 : _) -(_)> ();

False = f @-(1)> @False f;

@(F @=(2)> (P $ 4) => (@F P, @F P));

F = F @=(1, 0)> @F

@(False @=(2)> (f $ 1 : f @-(1)> @False f) =>
  (P $ 1 : (f $ 1 : f @-(1)> @False f) -> Type) -(1)> P f)

(f $ 1 : f @-(1)> @False f) =>
  (P $ 1 : (f $ 1 : f @-(1)> @False f) -> Type) -(1)> P f

False = False @=(n)>
  f -(1)> (P $ 1 : (f $ 1 :) -> Type) -(1)>
(A $ 2 : Type) -> (x $ 1 : A) -> A

Fix = (x $ 2 : @Fix) -(0)> ();
fix = (x $ 2 : @Fix) =(0)> x x;

T_F = F @-(1)> (A : Type) -> Type;
F = F @=(1)> @F;
@(F @=(1)> @F);

Unit = Unit @=(1, 0)>
  u @-(1, 0)> (P $ (2, 0) : (u $ (1, 0) : Unit) -> Type) ->
    P (u @=(1, 0)>
      (P $ (2, 0) : (u $ (1, 0) : Unit) -> Type) =>
        (x : P u) => x
      ) -> P u;

fix = (x : Fix $ 0, 0) =(0)>
(A : Type $ 2, 0) -> (x : A $ 0, 1) -> A;
()
(A : Type) => (B : ) => (x : A) =>


Term =
  | Type
  | x
  | (x : A) -> B
  | (x : A) => M
  | M N;

(A : Type) -> A;

Context = List Type;


-------------
Γ |- A : Type

Ind (T : Type) =
  (P : Type -> Type) ->
  P Type ->
  ((A : Type) -> (B : (x : A) -> Type) ->
    P A -> (x : A) -> P (B x) -> P ((x : A) -> B x)) ->
  P T;

x : Ind Type = P => p_type => p_forall => p_type;

T_Id = (A : Type) -> Type;
T_Id_ind : Ind T_Id = P => p_type => p_forall =>
  p_forall Type Type p_type p_type;


(A : Type) : Ind A = P => p_type => p_var => p_var A;

x => (A : Type) => (B : Type) => _

Dyn =
  (A : Type, x : A);

Ind {A} (T : A) =
  | Univ : Ind Type;
  | Forall
      A (a_dyn : Ind A)
      B (b_dyn : (x : A) -> Ind (B x))
    : Dyn ((x : A) -> B x);
  | Lambda
      A (a_dyn : Ind A)
      B (b_dyn : (x : A) -> Ind (B x))
      M (m_dyn : (x : A) -> Ind (M x))
    : Dyn ((x : A) => (M x : B x));

Dyn = (A : Type, T : A, ind : Ind T);


False @-(0)> (f : f @-(0)> False f) -> Type;

----------------------
Γ |- x @-(0)> T : Type

----------------------------
Γ |- x @=(0)> M : x @-(0)> T


Γ, x : x @-(l)> T : T |- Type
-----------------------------
Γ |- x @-(1 + l)> T : Type


Γ, x : x @-(l)> T : T |- Type
-----------------------------
Γ |- x @-(d)> T : Type

(w : Type $ ω) -> 1

Γ, x : x @-(l)> T : T |- Type
-----------------------------
Γ |- (d, False) : Type $ ω

(d, False) @-> (f : (d, f) @-> @False d f) -> Type;

Γ, x : x @-(l)> T : M |- T[x := x @=(l)> M]
-------------------------------------------
Γ |- x @=(1 + l)> M : x @-(1 + l)> T





----------------------
Γ |- x @=(0)> M : x @-(l)

-------------------
Γ |- x @-> T : Type

False = False @=>
  f @-> (P : @False -> Type) -> P f;

Γ, x : x @-(l)> T : T |- Type
-----------------------------
Γ |- x @-(l)> T : Type

Term =
  | Grade
  | Type
  | (x : A) -> B
  | (x : A) => M
  | M N;

Type : Type $ 0
(x : A, y)
Type $ 2
(x : ?)

Type : Type $ 0

Unit = Unit @=> (G : Grade) ->
  u @-(G)> (P : @Unit -> Type) -> P (u @=(G)> P => x => x) -> P u;

x @-(G)> ()
(x : ((G : Grade) -(G)> Nat) $ 1)

(x : ((G : Grade) -(G)> Nat G) $ 1)
(G : Grade) ->

Γ |- A : Type $ n   Γ |- B : Type $ 1
-------------------------------------
Γ |- (x : A) -> B :


Γ |- x :
-------------------------------------
Γ |- x @-> T :

False @-> (f : f @-> @False f) -> Type;

False_C = (A : Type) -> A;
False_0 = (f_c : False_C, i : (P : False_C -> Type) -> P f_c);
False_1 = (f_0 : False_0, i : (P : False_0 -> Type) -> P f_0);
False_2 = (f_1 : False_1, i : (P : False_1 -> Type) -> P f_1);


Γ, x : x @-> (G : Grade) -> T, G : Grade |- T : Type $ G
--------------------------------------------------------
Γ |- x @-> (G : Grade) -> T :

Γ, x : x @-> (G : Grade) -> T, G : Grade |- T : Type $ G
--------------------------------------------------------
Γ |- x @-> (G : Grade) -> T : Type $ ω

False @-> (G : Grade) -> (f : f @-> (G : Grade) -> @False G f) -> Type;

False @-(1)> (f : f @-(1)> @False f) -> Type;

False = (G, False) @=> ((G, f) @-> (P : @False G -> Type) -> P f) G;

@False 0 === Base
@False 1 === f @-> (P : @False 0 -> Type) -> P f



T_False = False @-> (f : f @-> @False f) -> Type;
T_False_C = Type;
T_False_0 = (f : False_C) -> Type;




@False == f @-(1)>
  (P : @(False @=(0)> f @-(1)> (P : @False -> Type) -> P f) -> Type) ->
  P f

False_0 f_c = (P : False_C -> Type) -> P f_c;
False_1 f_0 = (P : False_C -> Type) -> P f_0;

Bool_C = (A : Type) -> A -> A -> A;
true_c : Bool_C = A => x => y => x;
false_c : Bool_C = A => x => y => y;

Bool_0 b_c = (P : Bool_C -> Type) -> P true_c -> P false_c -> P b_c;


Γ |- M[G := 0][x := (G, x) @=> M] : T[G := 0][x := (G, x) @=> M]

Γ |- M[G := 0][x := (G, x) @=> M] : T[G := 0][x := (G, x) @=> M]
----------------------------------------------------------------
Γ |- (G, x) @=> M : (G, x) @-> T

(G, False) @=> (G, f) @-> (P : False@G -> Type) -> P f;


(G, f) @-> (P : False@G -> Type) -> P f

(G, f) @-> (P : ((G, f) @-> (P : False@G -> Type) -> P f) -> Type) -> P f;


f @-(G)> (
  b : (A : Type) -> A,
  i : (P : False@G -> Type) -> P f
);

f @-(0)> (
  b : (A : Type) -> A,
  i : (P : False@G -> Type) -> P f
) === (A : Type) -> A

f @-(1)> (
  b : (A : Type) -> A,
  i : (P : False@G -> Type) -> P f
) === (P : False@G -> Type) -> P f

f @-> (P : False@G -> Type) -> P f


Γ, x : x @-(G)> T |- T : Type
-----------------------------
Γ |- x @-(1 + G)> T : Type

False @-(0)> (f : f @-(1)> @False f) -> Type



Γ, x : x @-(G)> T |- T : Type
-----------------------------
Γ |- x @-(1 + G)> T : Type

Unit @=(1)> u @-> (P : @Unit -> Type) ->
  P (u @=> P => x => x) -> P u;


Γ, x : x @-(G)> T |- T : Type
-----------------------------
Γ |- x @-(1 + G)> T : Type

Γ |- M : x @-(0)> T
------------------------- // Lower Base
Γ |- lower M : Unit

Γ |- M : x @-(1 + G)> T
------------------------- // Lower Succ
Γ |- lower M : x @-(G)> T

------------------------------------------ // Lower Base Compute
Γ |- lower (x @=(0)> M) === unit

------------------------------------------ // Lower Succ Compute
Γ |- lower (x @=(1 + G)> M) === x @=(G)> M

Γ |- M[x := lower M] : T[x := lower M]
-------------------------------------- // Fix Succ
Γ |- x @=(G)> M : x @-(G)> T

Γ |- M : x @-(0)> T
---------------------- // Unroll
Γ |- @M : T[x := unit]

Γ |- M : x @-(G)> T
------------------------- // Unroll Typing
Γ |- @M : T[x := lower M]

Γ |- M : x @-(G)> T
------------------------- // Unroll Compute
Γ |- @M : T[x := lower M]

// extensions
Γ, x : lower (x @-(G)> T) |- M : T[x := lower M]
------------------------------------------------ // Fix Weak
Γ |- x @=(G)> M : x @-(G)> T



Γ |- M : (x $ n) @-> T $ 1 + n
------------------------------ // Unroll
Γ |- @M : T[x := M] $ 1

Γ |- M : (x $ n) @-> T $ 1 + n
--------------------------------------------- // Unroll Compute
Γ |- @((x $ n) @=> M) : M[x := (x $ n) @=> M]


Γ, x : (x $ n) @-> T |- M : T[x := (x $ n) @=> M]
-------------------------------------------------
Γ |- (x $ n) @=> M : (x $ n) @-> T



(False $ 1) @-> Type;

(False $ 0) @=> (A : Type) -> A;
(False $ 1 + G) @=> f @-> (P : @False -> Type) -> P f;

(False $ 1) @=> f @-> (P : @False -> Type) -> P f
(False $ 1) @=> f @-> (P : @False -> Type) -> P f;



case : (b : Bool) -> (A : Type) -> A -> A -> A;
Bool = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;


ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
Bool = (P : Bool -> Type) -> P true -> P false -> P b;

Bool : Type;
true : Bool;
false : Bool;

Bool = b @-> (P : Bool -> Type) -> P true -> P false -> P b;
true = P => x => y => x;
false = P => x => y => y;

Γ, x : x @-> T |- T : Type
-------------------------- // Self
Γ |- x @-> T : Type

Γ, x : x @-> T |- M : T[x := x @=> M]
------------------------------------- // Fix
Γ |- x @=> M : x @-> T


(x $ 2) => x + x

x0 => x1 => x0 + x1

(x => x x) (x => x x)

Either A B =
  | Left (content : A)
  | Right (content : B);

Either A B =
  (tag : Bool, content : tag Type A B);

(either : Either Int String) => (
  (tag, content : tag Type Int String) = either;

  ind tag (b => (b Type Int String) -> String)
    (content => Int.to_string content) (content => content) content
)


(False $ 0) @=> (A : Type) -> A;
(False $ 1 + G) @=> f @-> (P : @False -> Type) -> P f;


(Loop $ 0) @=> Unit
(Loop $ 1) @=> () -> @Loop

(Loop $ 1) @-> Type;

(Loop $ 2) @=> () -> @Loop;

@((Loop $ 2) @=> () -> @Loop)

(Loop $ 2) @=> () -> () -> Unit;

(Loop $ 2) @=> () -> @((Loop $ 1) @=> () -> @Loop)


Γ |- T : Type // try ((x $ 0) @-> T) $ 0
--------------------------------------------- // Fix Succ
Γ |- (x $ 0) @-> T : (x $ 0) @-> T

Γ, x : (x $ G) @-> T |- T : Type
--------------------------------------------- // Fix Succ
Γ |- (x $ 1 + G) @-> M : (x $ 1 + G) @-> T


Γ |- M : T // try ((x $ 0) @=> M) $ 0
------------------------------------- // Fix Base
Γ |- (x $ 0) @=> M : (x $ 0) @-> T

Γ, x : (x $ G) @-> T |- M : T[(x $ G) @=> M]
--------------------------------------------- // Fix Succ
Γ |- (x $ 1 + G) @=> M : (x $ 1 + G) @-> T


Γ, x : (x $ G) @-> T |- T : Type
-------------------------------- // Self Succ
Γ |- (x $ 1 + G) @-> T : Type


False : Type $ 0

(False $ 0) @=> Unit;
(False $ 1) @=> (f $ 1) @-> (P : @False -> Type) -> P f;
(False $ 2) @=> (f $ 1) @-> (P : @False -> Type) -> P f

False @-> (f : f @-> @False f) -> Type;


Γ |- Z : Type
------------------------------ // Self Base
Γ |- @self(0, Z). S : Type $ 0

Γ, x : @self(G, Z). S |- S : Type
-------------------------------------- // Self Succ
Γ |- @self(1 + G, Z). S : Type $ 1 + G


@self(0, Type).
  (f : @self(1, ). f @-> @False f)) -> Type;

@fix(
  (A : Type) -> Type,
  False =>
);G. T [G]

(G : Grade)


zero = z => z;
one = s1 => z => s1 z;
two = s2 => s1 => z => s2 (s1 z);
three = s3 => s1 => z => s3 (s2 (s1 z));


let Closed A = ∀(G : Grade). A [G]
// closed as it is unknown how many copies it will be needed(0..1)
let Bool : Type = ∀(A : Type). Closed A -> Closed A -> Closed A
let true : Closed Bool =
  // safe to ignore y as it is used 0 times
  ΛG. [ΛA. fun x y -> let [y] = y 0 in x]
let false : Closed Bool =
  ΛG. [ΛA. fun x y -> let [y] = x 0 in y]

// same applies to nats but (0..n)
let Nat : Type = ∀(A : Type). Closed A -> Closed (A -> A) -> Closed A;
let zero : Closed Nat =
  ΛG. [ΛA. fun z s -> let [s] = s 0 in z];
let one : Closed Nat =
  ΛG. [ΛA. fun z s -> let [s] = s 1 in s z];
let two : Closed Nat =
  ΛG. [ΛA. fun z s -> let [s] = s 2 in s (s z)];




False @-> (f : f @-> @False f) -> Type;

T_False_0 = Type;
T_False_1 (False_0 : T_False_0) = (f_0 : False_0) -> Type;
T_False_2 (False_0 : T_False_0) (False_1 : T_False_1 False_0) =
  (f_0 : False_0) -> (f : False_1 f_0) -> Type;

False_0 = (A : Type) -> A;
False_1 (f_0 : False_0) = (P : False_0 -> Type) -> P f_0;
False_2 (f_0 : False_0) (f_1 : False_1 f_0) =
  (P : (f_0 : False_0) -> False_1 f_0 -> Type) -> P f_0 f_1;

False_0 = (A : Type) -> A;
False_1 (f_0 : False_0) = (P : False_0 -> Type) -> P f_0;
False_2 (f_0 : False_0) (f_1 : False_1 f_0) =
  (P : (f_0 : False_0) -> False_1 f_0 -> Type) -> P f_0 f_1;

// something like the following
False n = (P : n Type Type _) -> n Type P _;


False_1 = @fix(2,
  (A : Type) -> A,
  False. (f : False) => (P : False -> Type) -> P f
);

False_1 = @fix(G,
  (A : Type) -> A,
  G -> False -> @self(G, False,
    G -> f -> (P : False G -> Type) -> P f)
);

False G = @fix(G,
  (A : Type) -> A,
  G -> False -> @self(G, False,
    G -> f -> (P : False G -> Type) -> P f)
);

False = @fix(1,
  (A : Type) -> A,
  G -> False -> @self(1 + G, False,
    G -> f -> (P : False G -> Type) -> P f)
);
False = @self(1, (A : Type) -> A,
    G -> f -> (P : False G -> Type) -> P f)


Unit = @fix(1,
  (A : Type) -> A -> A,
  G -> Unit -> @self(1 + G, Unit,
    G -> u -> (P : Unit G -> Type) -> P unit -> P u)
);

Unit =
  @self(1, (A : Type) -> A -> A,
    G -> u -> (P : Unit G -> Type) -> P unit -> P u)
unit = @fix(1, A => x => x,
  G -> u -> P => x => x);




T_False G = @self(G, G => False => (f : False G) -> Type);
False G = @fix(G, G => False => (f : False G) => (P : False G -> Type) -> P f);

T_False G = @self(G, G => False => (f : False G) -> Type);

T_False_1 = @self(1, Type, False. (f : False) -> Type);

False_1 = @fix(1, (A : Type) -> A, False. f => (P : False -> Type) -> P f);


T_Unit_1 = @self(1, Type, Unit. (f : False) -> Type);
@self(1, Type, False. (f : False) -> Type);


Γ |- Z : Type
--------------------------------- // Self Base
Γ |- @self(0, Z, x. S) : Type $ 0

Γ, x : @self(G, Z). S |- S : Type
----------------------------------------- // Self Succ
Γ |- @self(1 + G, Z, x. S) : Type $ 1 + G

@self(1, Type, False. (f : False) -> Type);


@fix(False, f) @=> (P : False -> Type) -> P
@self(0, Type),


False @-> (f : False )
@self(1, Type, G => False => (f : False G) -> Type)

Unit = (P : W Type) -> I P -> S P;

Term =
  | Grade
  | Type
  | (x : A $ n) -(m)> B
  | (x : A $ n) =(m)> M
  | M N;

case : (b : Bool) -> (A : Type) -> A -> A -> A;
Bool = (A : Type) -> A -> A -> A;

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b;
Bool = b @-> (P : Bool -> Type) -> P true -> P false -> P b;

(b : Bool) => @b : (P : Bool -> Type) -> P true -> P false -> P b


Γ, x : x @-> T |- T : Type
--------------------------
Γ |- x @-> T : Type

Γ |- M : x @-> T
-------------------
Γ |- @M : T[x := M]


False @-> (f : f @-> False f) -> Type;


Γ |- G : Grade  Γ |- Z : Type
Γ, G : Grade, False : @self(G, Z, G => False => S) |- S : Type
--------------------------------------------------------------
Γ |- @self(G, Z, G => False => S) : Type

Γ |- Z : Type
--------------------------------------------
Γ |- @self(0, Z, G => False => S) : Type

Γ, False : @self(d, Z, G => False => S) |- S[G := d] : Type
-----------------------------------------------------------
Γ |- @self(1 + d, Z, G => False => S) : Type



@self(0, Type, G => False =>
  (f : @self(G, False_B, G => f => False G f)) -> Type);


@self(1, Type, G => False =>
  (f : @self(G, False_B, G => f => False G f)) -> Type);

(False : ) =>
  (f : @self(1, False_B, G => f => False G f)) -> Type

@self(2, Type, G => False =>
  (f : @self(G, False_B, G => f => False G f)) -> Type);


@fix(G, False_B, G => False =>
  f => (P : False G f -> Type) -> P f)

@self(0, Type, G => False => Type);

@fix(1, False_B, G => False =>
  @self(G, False_B, G => f => (P : False@G -> Type) -> P f))


False = @fix(False_B, G => False =>
  @self(False_B, G => f => (P : False@G -> Type) -> P f)@G);

False_0 = False@0;
False_0 = False_B;
False_1 = @self(False_B, G => f => (P : False@G -> Type) -> P f)@1;

Unit_B = (A : Type) -> A -> A;
unit_b : Unit_B = A => x => x;

Unit G = @fix(Unit_B, G => Unit =>
  @self(Unit_B, G => u => (P : Unit@G -> Type) ->
    P (@fix(unit_b, G => u => P => x => x)@G) -> P u)@G)@G;
Unit_0 = Unit_B;
unit_0 = unit_b;
Unit_1 = @self(Unit_B, G => u => (P : Unit@G -> Type) ->
    P (@fix(unit_b, G => u => P => x => x)@G) -> P u)@1;
unit_1 : Unit_1 =
  @fix(unit_b, G => u => P => (x : P u) => x)@1;

@unit_1 :
  (P : Unit@0 -> Type) ->
    P (@fix(unit_b, G => u => P => x => x)@0) -> P (lower unit_1);


Γ |- Z : Type
--------------------------------------------
Γ |- @self(0, Z, G => False => S) : Type

Γ, False : @self(d, Z, G => False => S) |- S[G := d] : Type
-----------------------------------------------------------
Γ |- @self(1 + d, G => False => S) : Type

@self(1, False_B, G => f => (P : False@G -> Type) -> P f)

Γ |- Z : Type
--------------------------------------------
Γ |- @self(0, Z, G => False => S) : Type

f => (P : False 0 f -> Type) -> P f

@fix(1, False_B, G => False =>
  f => (P : False G f -> Type) -> P f)


f => (P : () G f -> Type) -> P f


False_B = (A : Type) -> A;
T_False G = @self(G, Type, G => False =>
  (f : @self(G, False_B, G => f => False G f)) -> Type);
False G = @fix(G, False_B, G => False => f =>
  (P : @self(G, False_B, G => f => False G f) -> Type) -> P f);

: @self(G, Type, G => False => (f : False G) -> Type)
= @fix(G, False_B, G => False => );

: @self(G, Type, G => False => _)
= @fix(G, (A : Type) -> A, False => _)

T_False_0 = Type;
T_False_1 (False_0 : T_False_0) = (f_0 : False_0) -> Type;
T_False_2 (False_0 : T_False_0) (False_1 : T_False_1 False_0) =
  (f_0 : False_0) -> (f : False_1 f_0) -> Type;

False_0 = (A : Type) -> A;
False_1 (f_0 : False_0) = (P : False_0 -> Type) -> P f_0;
False_2 (f_0 : False_0) (f_1 : False_1 f_0) =
  (P : (f_0 : False_0) -> False_1 f_0 -> Type) -> P f_0 f_1;


Γ |- G : Grade  Γ |- A : Type
Γ, g : Grade, x : @self.lower(@self(G, A, g => x => B))
  |- B : Type
-------------------------------------------------------
Γ |- @self(G, A, g => x => B) : Type


Γ |- M : A
Γ, g : Grade, x : @self.lower(@self(G, A, g => x => B))
  |- N : B[x := @fix.lower(@fix(G, M, g => x => N))]
-------------------------------------------------------
Γ |- @fix(G, M, g => x => N) : @self(G, A, g => x => B)

Γ |- M : @self(G, A, g => x => B)
---------------------------------
Γ |- @M : B[x := @fix.lower(M)]


Γ |- G : Grade
Γ, g : Grade, x : @self.lower(G, g => x => T) |- T : Type
---------------------------------------------------------
Γ |- @self(G, g => x => T) : Type

Γ, g : Grade, x : @self.lower(G, g => x => T)
  |- M : T[x := @fix.lower(@fix(G, g => x => M))]
----------------------------------------------------
Γ |- @fix(G, g => x => M) : @self(G, g => x => T)

Γ |- M : @self(G, g => x => T)
-------------------------------
Γ |- @M : T[x := @fix.lower(M)]



False @-> (f : f @-> @False f) -> Type;

@self(G, G => False => (f : @self(G, G => f => G@False f)) -> Type);


(False : @self(0, G => False => (f : @self(G, G => f => G@False f)) -> Type)) =>
  (f : @self(0, G => f => G@False f)) -> Type;

(False : Unit) => (f : Unit) -> Type
@self(0, G => False => (f : @self(G, G => f => G@False f)) -> Type)
@self(1, G => False => (f : @self(G, G => f => G@False f)) -> Type)

T_False G = @self(G, G => False => (f : @self(G, G => f => G@False f)) -> Type);

False : @self.lower(G, G => False => (f : @self(G, G => f => G@False f)) -> Type);
f : @self.lower(G, G => f => G@False f)
False G = @fix(G, G => False => f =>
  (P : (f : @self(G, G => f => G@False f))) -> P f);


T = (A : Type $ 0) -> A -> A;
T = (A : Type $ (2, 0)) -> A -> A;
T = (A : Type $ (2, 1)) -> A -> A;
Fix = Fix @=> (x : Fix $ 0) -(0)> (A : Type) -> A;

TFix = Fix @-> Type;
Fix = Fix @=> (x : Fix $ 0) -(0)> (A : Type) -> A


(x : Fix $ (0, 0)) =(0)> x x;


fix : Fix = x => x x;


x : False $ 0 = fix fix;

sock = (socket : Socket$) => ();

Bool = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;

not : Bool -> Bool = b => b Bool false true;

Eq A x y = (P : A -> Type) -> P x -> P y;
refl A x : Eq A x x = P => x => x;


make = (l : Int & l >= 0) => _;

id
  : <A : Type>(x : A) -> A
  = <A : Type> => (x : A) => x;

id_string : (x : String) -> String = id<String>;
1 >= 0
| Some one_gte_zero => make (1 & one_gte_zero)
| None

true_eq_true : Eq Bool true true = refl _ _;

true_eq_not_false : Eq Bool true (not false) = refl _ _;
true_eq_not_true : Eq Bool true (not true) = refl _ _;

b_neq_not_b : Eq Bool true (not false) = _;

if_pred_then_string_else_int
  : (pred : Bool) -> (x : pred Type Int String) -> pred Type Int String
  = (pred : Bool) => (x : pred Type Int String) => x;


f : (x : Int) -> Int
  = if_pred_then_string_else_int true

g : (x : String) -> String
  = if_pred_then_string_else_int false


Fix = Fix @=> (x : Fix $ (1, 0)) -(0)> (A : Type) -> A

(x : Fix $ (1, 0)) =(0)> x x;

(x : Fix $ 0) -> x x
(f : False $ 0) => (x : P f) =>

---------------
: t : A $ 0


Fix = Fix @=> (x : Fix $ (1, 0)) -(0)> (A : Type) -> A
(x : Fix $ (1, 0)) =(0)> x x;


False = (False $ (2, 0)) @=(0)> (f : (f $ (1, 0)) @-> @False f) =>
  (P : (f $ (1, 0)) @-> @False f) -> P f;

False = (False $ (2, 0)) @=(0)> (f : (f $ (_, 0)) @-> @False f) =>
  (P : (f $ (_, 0)) @-> @False f) -> P f;

T_T = (T $ (1, 0)) @=(0)> (A : Type) -> A;

T : T_T = T @=> @T;


Type : Type

A : Type 0 = Int;
A : Type 1 = Type 0;

Type n : Type (n + 1)

double = (x : Nat $ 2) => x + x;
double = x => x + x;

case : (b : Bool) -> (P : Bool -> Type) ->
  P true -> P false -> P b;

b
| true => ()
| false => ();

("a" : Dyn)

if "a" then 1 else 2
x : Int = 1;

false : (A : Type) -> A = _;
id : (A : Type) -> A -> A = _;

incr : Int -> Int = _;

incr_x_is_plus_one : (x : Nat) -> incr x == x + 1 = _;

may_loop_forever : Int ->! Int = _;


double = (x : Nat $ 2) => x + x;
quadruple = x => double (double x);


false : ((A : Type) -> A) $ 0 = _;

b
| true => ()
| false => ();

case : (b : Bool) -> (P : Bool -> Type) ->
  P true -> P false -> P b;


Not (T) = (A <: T) -> A;
Theta = (A <: Top) -> Not ((B <: A) -> Not B);
f = (A0 <: Theta) => (A0 <: (A1 <: A0) -> Not A1);



Not T = (A <: T) -> A;
Theta = (A <: Top) -> Not ((B <: A) -> Not B);
f = (A0 <: Theta) => (A0 <: (A1 <: A0) -> Not A1);


(A : *) => (x : A) => x;
double = (x $ (0, 2)) => x + x;n


Not T = (A <: T) -> A;
Theta = (A <: Top) -> Not ((B <: A) -> Not B);
f = (A0 <: Theta) => (A0 <: (A1 <: A0) -> Not A1);

context = [A0 <: Theta];
received :: A0;
expected :: (A1 <: A0) -> Not A1;

context = [A0 <: Theta];
received :: (A1 <: Top) -> Not ((A2 <: A1) -> Not A2);
expected :: (A1 <: A0) -> Not A1;

context = [A0 <: Theta; A1 <: A0];
received :: Not ((A2 <: A1) -> Not A2);
expected :: Not A1;

context = [A0 <: Theta; A1 <: A0];
received :: (A2 <: Top) -> Not ((A3 <: A2) -> Not A3);
expected :: (A2 <: A1) -> Not A2;


Type : Type

Term =
  | Var (x : String)
  | Lam (body : Term -> Term);

Ind (A : Type) (x : A) =
  | Univ : Ind Type Type
  | Forall
      A (A_dyn : Ind Type A)
      B (B_dyn : (x : A) -> Ind A x -> Ind Type (B x))
    : Ind Type ((x : A) -> B x)
  | Lambda
      A (A_dyn : Ind Type A)
      B (B_dyn : (x : A) -> Ind A x -> Ind Type (B x))
      M (M_dyn : (x : A) -> Ind A x -> Ind (B x) (M x))
    : Ind ((x : A) -> B x) ((x : A) => M x);

Dyn = (A : Type, x : A, Ind A x)

uip : (A : Type) -> (x : A) -> (a : x == x) -> a == refl = _;


Impredicative Universe + Negative Recursin + Subtyping = _;


(b : Bool $ 1 ~ 2) -> (P : Bool $ 0 ~ 2 -> Type) ->
  P true $ 1 ~ 0 -> P false $ 1 ~ 0 -> P b;

(x : Nat $ 0 ~ 2) -(0)> Nat;

((x $ 0 ~ 2) =(0)> x + x)

((x $ 2 ~ 2) => x + x)

id : 'A -> 'A = x => x;

id : <A>(x : A) -> A = x =>


T = Int $ 1 ~ 0;


(x : A $ n ~ m) =($ 0 ~ 0)> x


Fix = (x : Fix $ 0 ~ 0) -(0)> (A : False) -> A;
fix = (x : Fix $ 0 ~ 0) =(0)> x x;

false : ((A : False) -> A) $ 0 = fix fix;


Fix = (x : Fix) -> (A : False) -> A;
fix : Fix = x => x x;


Γ |- M : (x $ n ~ m) @-> T $ 1 + n ~ 1 + m
------------------------------------------
Γ |- @M $ 1 ~ ?


(F $ n ~ m) @=> @F



T_False G = @self(G, G => False => (f : @self(G, G => f => G@False f)) -> Type);

False : @self.lower(G, G => False => (f : @self(G, G => f => G@False f)) -> Type);
f : @self.lower(G, G => f => G@False f)
False G = @fix(G, G => False => f =>
  (P : (f : @self(G, G => f => G@False f))) -> P f);

False = False @=> f @-(1)> (P : False -> Type) -> P f;

False @-(0)> Type;

False = (False $ 0 ~ 1) @=(0)> (f $ 0 ~ 1) @-(1)>
  (P : False $ 0 ~ 1 -(0)> Type) -> P f;

Unit = (Unit $ 0 ~ ) @=(0)> (u $ 0 ~ 1) @-(1)>
  (P : Unit $ 0 ~ 1 -(0)> Type) -> P unit -> P u;

False = (False $ 0 ~ 1) @=(0)> (f $ 0 ~ 1) @-(1)>
  (P : False $ 0 ~ 1 -(0)> Type) -> P f;

(F $ 0 ~ 1) @=(0)> @F

False = (False $ 0 ~ 1) @=(0)> (f $ 0 ~ 1) @-(1)>
  (P : False $ 0 ~ 1 -(0)> Type) -> P f;

T = (f $ 0 ~ 1) @-> (P : False $ 0 ~ 1 -> Type) -> P f;
T = (u $ 0 ~ 1) @->
  (P : @Unit $ 0 ~ 1 -> Type) -> P unit -> P u;


Unit = (A : Type) -> A -> A;
unit : Unit = A => x => x;

Unit_0 : Type = (u : Unit_B ~ 0) @-> (P : Unit -> Type) -> P unit -> P u;
unit_0 : Unit_0 = u @=> P => x => x;

Unit_1 = (u : Unit_0 ~ 1) @-> (P : Unit_0 ~ 1 -> Type) -> P unit_0 -> P u;
unit_1 : Unit_1 = u @=> P => x => x;

Unit_2 = (u : Unit_1 ~ 1) @-> (P : Unit_1 ~ 1 -> Type) -> P unit_1 -> P u;
unit_2 : Unit_2 = u @=> = P => x => x;

Γ |- A : Type  Γ, x : A |- B : Type
-----------------------------------
Γ |- (x : A) @-> B : Type

Γ |- A : Type  Γ, x : A |- M : T[]
-----------------------------------
Γ |- (x : A) @=> M : (x : A) @-> T

Γ |- M : (x ~ n) @-> T $ 2 ~ 1
------------------------------------
Γ |- @M : [x := ] $ 1

False_0 = (f ~ 0) @-> (A : Type $ 0) -> A;
False_1 = (f ~ 1) @-> (P : False_0 -> Type) -> P f;
False_2 = (f ~ 1) @-> (P : False_1 -> Type) -> P f;
False_3 = (f ~ 1) @-> (P : False_2 -> Type) -> P f;

@fix(1, (G ~ _) => (False ~ G) =>
  (f $ G) @-(1)> (P : False@G $ 0 ~ G -> Type) -> P f);

False : Unit $ 0 ~ 0

(f $ 0 ~ 0) @-(1)>
  (P : False@0 $ 0 ~ 0 -> Type) -> P f

False @-> (f : f @-> @False f) -> Type;

(False $ 0 ~ 0) @-> (f : (f ~ 0) @-> @False f) -> Type;

Why CoC?

incr = (x : Int) => x + 1;

id
  : (A : Type) -> (x : A) -> A
  = (A : Type) => (x : A) => x;

id = id ((A : Type) -> (x : A) -> A) id;

Bool = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;

int_or_string
  : (pred : Bool) -> (x : pred Type Int String) -> pred Type Int String
  = (pred : Bool) => (x : pred Type Int String) => x;

x
  : (x : Int) -> Int
  = int_or_string true;

y
  : (x : String) -> String
  = int_or_string false;

mergesort == bubblesort

(A : Type) -> (l : List A) -> mergesort l == bubblesort l;

uip : (A : Type) -> (x : A) -> (eq : x == x) -> eq == refl = _;


Type 0
Type 1
Type 2

(x : Int $ 2) => x + x;
(x0 : Int) => (x1 : Int) => x0 + x1;
(x : Nat 2) => x + x;
(x0 : Nat) => (x1 : I_nat) => _;

(x : A $ 4) => (x : Nat $ 4 = 1; x)


incr = (x : Int) => x + 1;

User =
  | Anonymous({ name : string })
  | Registered({ id : int; name : string });

is_registered = user =>
  user
  | Anonymous(_) => false
  | Registered(_) => true;

name_of_registered_user = (user : User & is_registered(user)) =>
  user
  | Registered { id; name } => Registered { id; name }

(x
x => M
M N)

true = x => y => x;
false = x => y => y;

Type : Type;

Fix = Fix $ 0 -(0)> ();
(x : Fix $ 0) =(0)> x x;


id = (A : Type) => (x : A) => (
  @debug(x)
);

find_user : (id : Nat) -> Eff [DB.read] User;

x = @debug.db(find_user(1));

f = id(x => x);

User = {
  parents : List User;
};

Exist<A> = {
  x : A;
};

_A `unify` Int

id
  : <A>(x : A) -> A
  = (x : _A) => x;



Bool : Type = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;


Bool : Type = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;

id
  : <A>(x : A) -> A
  = x => x;

f = id(1)

nat_or_string
  : (pred : Bool) -> (x : pred Type Nat String) -> pred Type Nat String
  = (pred : Bool) => (x : pred Type Nat String) => x;

(x : Nat) ->? Nat

Socket : {
  close : (sock : Socket$) -> ();
} = _;


[@wasm] [@parallel]
f = List.map;

f = (sock : Socket$) => Socket.close sock;

double = (x : Nat $ 2) => x + x;
f = x => double x + double x;

make = (l : Int & x >= 0) =>

f
  : (x : Nat) -> Nat
  = nat_or_string true;
g
  : (x : String) -> String
  = nat_or_string false;


main : IO ()

f x

arr => (
  (x, arr) = Array.get(arr, 0);
  (y, arr) = Array.get(arr, 1);
  (x + y, arr)
);

pred (1) (0)

zero = z => s => z;
succ = n => z => s => s (n z s);

one = z => s => s z;
two = z => s => s (s z);
three = z => s => s (s (s z));


(x : ? -> Nat) => x x;
(x => x(x))(x => x(x))

((x : Int) => x + 1) 1
1 + 1
2;

(A : Type) => (x : A) => x;

x + 1 = 2

f (x + 1) = f (2)

(x => x - 1) (x + 1) = (x => x - 1) (2)
x + 1 - 1 = 2 - 1
x = 2

incr = (x : Int) => x + 1;

id
  : (A : Type) -> (x : A) -> A
  = (A : Type) => (x : A) => x;

Id = (A : Type) => A;

f
  : (x : String) -> String
  = id String;

g
  : (x : Nat) -> Nat
  = id Nat;

incr = x => x + 1;

incr 1 === 1 + 1

(P : Nat -> Type)

P 0
P n -> P (1 + n)


P 5

(P 0)

P 0 -> P (1)
P 1 -> P (2)
P 2 -> P (3)

Type : Type

Type 0 : Type 1
Type 1 : Type 2

((A : Type 0) -> A -> A) : Type 0
((A : Type 1) -> A -> A) : Type 2


((A : Type 0) -> A -> A) : Type 1
((A : Type 1) -> A -> A) : Type 2


absurd : (A : Type) -> A = _;

if : (b : Bool) -> (A : Type) -> A -> A -> A;
Bool = (A : Type) -> A -> A -> A;

ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b = _;

Bool = (P : Bool -> Type) -> P true -> P false -> P b;
Bool = (b : Bool) @-> (P : Bool -> Type) -> P true -> P false -> P b;

ind : (L : Level) ->
  (b : Bool (1 + L)) -> (P : Bool L -> Type) -> P true -> P false -> P (lower b) = _;

(n : Nat) -> S n != n

(n : Nat (1 + L)) -> S (lower n) != (lower n)


3 + 4 = 7
S S S Z + S S S S Z = S S S S S S S Z

2 * 3
S S Z * S S S Z = S S S S S S Z


Bool = (A : Type) -> A -> A -> A;
true : Bool = A => x => y => x;
false : Bool = A => x => y => y;

Bool = (A : Type) ->
  ((G : Grade) -> A $ G) $ 1 ->
  ((G : Grade) -> A $ G) $ 1 ->
  ((G : Grade) -> A $ G) $ 1;
true : Bool = A => x => y => (
  _ = y 0;
  x
);
false : Bool = A => x => y => (
  _ = x 0;
  y
);

Nat = (A : Type) -> A -> (A -> A) -> A;

Nat = (A : Type) ->
  A $ 1 ->
  ((G : Grade) -> (A -> A) $ G) $ 1 ->
  A $ 1;
zero : Nat = A => z => s => (
  _ = s 0;
  z
);
one : Nat = A => z => s => (
  s = s 1;
  s z
);
two : Nat = A => z => s => (
  s = s 2;
  s (s z)
);
three : Nat = A => z => s => (
  s = s 3;
  s (s (s z))
);
(x : Nat $ 1) => (y : Nat $ mul_copies(x)) => x * y



1 : Nat

1 : Int

f = (x : Int) => x;

f 1;

add : (A <: Number) -> A -> A -> A = _;

add Nat 1 1 : Nat
add Int -1 1 : Int
add Ratio (-1 / 1) (1 / 2) : Ratio


(-A) -> +B
Array A

Array Nat :> Array Int
Array Int :> Array Nat

f : (Nat -> Nat) -> Nat = _;

f ((x : Int) => 1)
f ((x : Int) => 1)

=
Decidability
Consistency
Impredicativity
Abstractions
Induction
Subtyping
Substructural

Graded Self

Unit_B = (A : Type) -> A -> A;
unit_b : Unit_B = A => x => x;

Unit_0 = (u : Unit_B) @-> (P : Unit_0 -> Type) -> P unit_b -> P u;
unit_0 = _;

@self()

Unit_0 = (u) @-> (P : Unit -> Type) -> P u

Closed A = (G : Grade) -> (A $ G)

(Unit $ 0 ~ 1) @=> u @-> (P : @Unit -> Type) -> P u;

(False $ 0 ~) @-> (f : f @-> @False f $ 0 ~ 1) -> Type;
(False $ 0 ~ 2) @->
  (I : I -> (f : ))

(A : Type $ 0 ~ 1) => (x : A $ 1 ~ 0) => x;

(A : Type) => x => (x : A $ 1 ~ 0);

(tag : Bool $ 1 ~ 1, payload : tag | true => Int | false => String)

Running

incr = x => x + 1;

two = incr(1);
two = (x => x + 1)(1);
two = (x + 1)[x := 1];
two = 1 + 1;
two = 2;

omega = (x => x(x))(x => x(x))
(x(x))[x := (x => x(x))]
(x => x(x))(x => x(x))
(x(x))[x := (x => x(x))]
(x => x(x))(x => x(x))

(let x = 1 in x + 1)
(x + 1)[x := 1]
1 + 1
2

(let x = 1 in x + 1)
(x => x + 1)(1)
(x + 1)[x := 1]

(let x = e0 in e1)
(x => e1)(e0)
e1[x := e0]

(let (x, y) = (1, 2) in x + 1)
((x, y) => x + 1)(1, 2)
x + 1[x := 1][y := 2]
x + 1[x := 1]
1 + 1


f = () => console.log(3);
f(console.log(1), console.log(2));


(() => console.log(3))(console.log(1), console.log(2));
console.log(3)

let f = fun () -> fun () -> print_endline "3" in
f (print_endline "1") (print_endline "2")


1 + (2 + (3 + (4 + (5 + 6))))

(1 + 2) + (3 + 4) + (5 + 6)
(1 + 2) + ((3 + 4) + (5 + 6))

(x => x(x))(x => x(x))

Teika

two = (
x = 1;
  x + 1
);
incr = (x $ 1) => x + 1;
double = x => x + x;
int_or_string = (b : Bool) =>
  (x : b | true => Nat | false => String) => x
id : <A>(x : A) -> A = x => x;
id : (A : Type) -> (x : A) -> A
  = (A : Type) => (x : A) => x;
Id = (A : Type) => A;
(x, y) = (x = 1, y = 2);
Joao = { id = 1; name = "João"; };
x = Joao.id;
l : Option Nat = Some 1;
User = { id : Nat; name : String; };
Either A B =
  (tag : Bool, tag | true => A | false => B);
data%Status =
  | Authorired
  | Banned { reason : String; };

Complete

// TODO: linearity constraints

----------------
Γ |- Type : Type

Γ |- A : Type  Γ, x : A |- B : Type
-----------------------------------
Γ |- (x : A) -> B : Type

Γ |- A : Type  Γ, x : A |- M : B
--------------------------------
Γ |- (x : A) => M : (x : A) -> B

Γ |- M : (x : A) -> B  Γ |- N : A
---------------------------------
Γ |- M N : B[x := N]

Γ |- t : A  Γ, A : Type, x : A |- B : Type
------------------------------------------
Γ |- @ind(t, A. x. B) : B[A := A][x := t]

Smol

---------------------
Γ | Δ |- M $ n : Type

--------------------
Γ | • |- Type : Type

Γ |- A : Type  Γ, x : A |- B : Type
-----------------------------------
Γ | • |- (x : A) -> B : Type

Γ |- A : Type  Γ, x : A |- M : B
--------------------------------
Γ |- (x : A) => M : (x : A) -> B

Γ |- M : (x : A) -> B  Γ |- N : A
---------------------------------
Γ |- M N : B[x := N]


((x : Socket) => Socket.close x)

Fix = (x : Fix $ 2) -> () -(0)> ();
fix = (x : Fix $ 1) =(0)> x;


Type : Type $ (n : Nat)
Nat : Type $ (n : Nat)
zero : Nat
succ : Nat -> Nat

(Type, Nat) @-> (Type : Type $ n, Nat : Type $ n);

Type @-> Type

Nat = n @-> (P : Nat -> Type) ->
  P zero -> ((n : Nat) -> P n -> P (succ n)) -> P n;
zero = P => z => s =>

Grade =
  (A : Type) -> A -> ((G : Grade) -> (A -> A) $ G) -> A

Γ |- A : Type  Γ |- n : Grade
-----------------------------
Γ |- M : A $ n

f = (x : Nat $ 2) => x + x;


@Type : Type
Type = @Type;

Bool = (A : Type) -> A -> A -> A;
Closed (El : Type) => = Closed @=>
  (T : Type) => (more : Bool) -> more T (());

Closed Unit false
Nat = Nat @=> (A : Type) -> A -> (Nat -> A) -> A;
fold = fold @=> (n : Nat) => A => z => s =>
  n A z (pred => fold A )


// Weird
Never = (A : Type) -> A;
Stop = (A : Type) -> (b : Never) -> b A;
Apply = (x : Never) -> (P : (x : Never) -> x Type) -> P x;

(s : Stop) => s
stop : Stop = A => b => b A;

Id = (A : Type) -> (B : Type) -> B -> A;

Apply = (x : Never) -> (P : (x : Never) -> x Type) -> P x;
apply : Apply = (x : Never) => (P : (x : Never) -> x Type) =>

(x : Never) => x;

Bool =
  b @-> (A : Type $ 0) -> A $ 1 -> A $ 1 -> A;

(x : (x : A) => A) => x

prefix _ infix
prefix _ infix _ infix _ suffix

x => {
  x
}
x => { x }
(1, )

(1, ...R)
(1, 2,)
{ a; b }

x | 0

6 + (6 / 6)

1 + (2 * 3) + 4


Bool = (A : Type) -> |A| -> |A| -> |A|;
Bool = (A : Type) -> [A] -> [A] -> [A];

(f : A $ 2) =>



Γ | Δ, x |- (x : A $ n) -> B : Type
------------------------------------
Γ | Δ |- (x : A $ 1 + n) -> B : Type

Γ | Δ |- A : Type   Γ, x : A | Δ |- B : Type
----------------------------------------
Γ | Δ |- (x : A $ 0) -> B : Type

Γ |- A : Type  Γ |- G : Grade
-----------------------------
Γ |- M : A $ G

Γ | Δ |- A : Type  Γ, x : A | Δ, x * 0 |- B : Type
--------------------------------------------------
Γ | Δ |- (x : A) -> B : Type



0 * Γ |- A : Type  0 * Γ |- G : Grade
-------------------------------------
0 * Γ |- A $ G : Type

Γ |- o  Γ |- M : A
0 * Γ |- G : Grade
------------------------------
G * Γ |- |M| : A $ G

Γ |- M : A $ G  Γ, x : A * G |- N : B
--------------------------------------
Γ, x : A * G |- |x| = M; N : B[x := N]



Γ |- A : Type
---------------
Γ |- |A| : Type

Γ |- o  Γ |- M : A
0 * Γ |- G : Grade
------------------------------
G * Γ |- M : |A|

Γ |- M : A $ G  Γ, x : A |- N : B
--------------------------------------
Γ, x : A * G |- |x| = M; N : B[x := N]



Closed (|A| : Type $ 0) = (|G| : Grade $ 0) -> A $ G;

(G : Grade $ 1) => (|x| : )

|x : Nat| = M; N
|x : Nat| = _; _


Closed A = (G : Grade $ 1) => (A * G);

(x : Closed Nat $ 1) => (G : Grade $ 2) =>
  (((x : Nat $ G) => (succ x $ G)) (x G));


f : (G : Grade $ 2) -(G)> Nat = _;
g : (G : Grade $ 1) -(G)> Nat = f; // subtyping



// great
(M)
<M>
[M]
{M}
|M|
// inverse
)M(
>M<
]M[
}M{
// consider
/M\
\M/

Smol

A core language, maybe try full linear + closed and add RC as a feature? Sum types can take closed terms.

Bool = (A : |Type|) -> (then : |A|) -> (else : |A|) -> |A|;

Γ | • |- M <= A
-----------------
Γ | • |- M <= |A|

Γ, x : A | Δ¹ |- M : |A|  Γ, x : A | Δ¹ |- N : B
------------------------------------------
Γ | Δ¹, Δ² |- |x : A| => M : (|x| -> B[x := ]

Closed A = (G : Grade $ 1) => (A $ G)
Fix = ()
Nat =


Bool = (A : Type $ 0) -> (then : |A|) -> (else : |A|) -> |A|;

Nat = (A : Type $ 0) -> (zero : A) -> (succ : |(acc : A) -> A|) -> A;
zero : Nat = A => zero => succ => (|| = succ; zero);
succ (pred : Nat) : Nat = A => zero => succ =>
  (pred A zero succ;


Dyn A = (G : Grade $ 1) -(G)> A;
Nat = (A : Type $ 0) -> (zero : A) -> (succ : Dyn ((acc : A) -> A)) -> A;
zero : Nat = A => zero => succ => (
  _ = succ 0;
  zero
);
succ (pred : Nat) : Nat = A => zero => succ => (
  succ = (G : Grade $ 1) => succ (1 + G);
);

@Nat = n @-> (P : Nat -> Type) ->
  P (n @=> P => z => s => (_ = s 0; z)) ->
  ((pred : Nat) ->)


λx. xP. P trueP false → ∀b. P b

Dyn A = (G : Grade $ 1) -(G)> A;

Nat : Type;
zero : Nat;
succ : Nat -> Nat;

Nat = (A : Type $ 0) -> A -> Dyn (A -> A) -> A;
zero = A => z => s => ()

Nat : Type;
zero : Nat;
succ : Nat -> Nat;

Nat = n @-> (P : Nat -> Type) -> P zero ->
  Dyn ((pred : Nat) -> P pred -> P (succ pred)) -> P n;
zero = P => z => s => z;


Nat = (A : Type $ 0) -> A -> |A -> A| -> A;
zero = A => z => s => (|| = s; z);
one = A => z => s => (|s1| = s; s1 z);
two = A => z => s => (|s2, s1| = s; s2 (s1 z));

Nat = (A : Type $ 0) -> A -> |A -> A| -> A;
zero : Nat = A => z => s => (s = s 0; z);
succ (pred : Nat) : Nat = A => z => s => (
  x = pred
);

Fix = (self : |Fix|) -> ();
|fix : Fix| = self => (
  |f, ...rest| = self;
  f(rest);
);

split : ((G : Grade) -> A $ (1 + G)) -> (A, (G : Grade) -> A $ G) = ?

@Fix = (self : (G : Grade) -(G)> Fix) -> ();
fix : (G : Grade) -(G)> Fix = G => self => (
  self : (G : Grade) -> Fix $ (1 + G)
    = G => self (1 + G);
  (f, self) = split self;
  f(self);
);
fix 1 fix

SNat = |(A : Type $ 0) -> A -> |A -> A| -> A|;


@Nat : Nat -> Type;
@zero : Nat zero;
@succ : (@pred : Nat pred) -> Nat (succ pred);

Nat k = (A : Type) -> A -> (A -> A) $ k -> A;
zero = A => z => s => z;
succ pred = A => z => s => s (pred A z s);


Nat : Type;
zero : Nat;
succ : Nat -> Nat;

Nat = n @-> (P : Nat $ 0 -> Type $ 0) ->
  P zero -> ((pred : Nat $ 0) -> P pred -> P (succ pred)) $ n -> P n;
zero = P => z => s => z;
succ pred = P => z => s => s (pred P z s);


Nat : Type;
zero : Nat;
succ : Nat -> Nat;

Nat = n @-> (P : Nat $ 0 -> Type $ 0) ->
  P zero -> ((pred : Nat $ 0) -> P pred -> P (succ pred)) $ n -> P n;
zero = P => z => s => z;
succ pred = P => z => s => s (pred P z s);


Nat = n @-> (A : Type) -> A -> (A -> A) $ n -> A;
zero : Nat = n @=> P => z => s => z;
succ (pred : Nat) : Nat = n @=> P => z => s => s (pred P z s);

f = () => () => 1;

x = (G : Grade) => (x : Nat $ G) => _;


A $ G
|M : A| $ G

Nat : Type;
zero : Nat;
succ : Nat -> Nat;

SRc : (A : Type $ 0) -> (n : Nat $ 1) -> Type;
next : (A : Type $ 0) -> (pred : Nat $ 0) -> SRc (succ pred) A -> (A, SRc pred A);
free : (A : Type $ 0) -> SRc zero A -> ();

Nat = n @-> (A : Type) -> A -> SRc n (A -> A) -> A;
zero = n @=> A => z => s => (() = free (A -> A) s; z);
succ = pred => n @=> A => z => s => (
  (s1, s) = next (A -> A) pred s;
  s1 (pred A z s)
);

SRc A n = () -> n Type () (acc => (A, acc));
next A pred rc = rc ();
free A rc = rc ();

(x : Unit) =>


(x : EUR $ 2) -(3)> USD


Nat : Type;
zero : Nat;
succ : Nat -> Nat;

SRc : (n : Nat) -> (A : SRc n Type) -> Type;

id = (A : SRc 0 Type) => A (A => (
  (x : A) => x,
  A
));

same : (n : Nat $ 0) -> (A : Type $ 0) ->
  (rc : SRc A (succ n)) ->
  fst (next rc) == fst (snd (next rc));


Nat = n @-> (A : Type $ 0) -> A -> (A -> A) $ n -> A;
zero = n @=> A => z => s => (
  () = A;
  () = s;
  z
);
succ = pred => n @=> A => z => s => (
  () = A;
  (s1, s) = s;
  s1 (pred A z s)
);

( $ ) n A = n Type () (acc => (A, acc));
next A pred rc = rc;
free A rc = (() = A; rc);


@E : (A : E Type) -> Type;
@E A = A;

(A : E Type) => (x : E ())
id = (A : Type) => (x : A) => x;
id = (A : Type $ 0) =>




Nat : Type;
zero : Nat;
succ : (pred : Nat) -> Nat;

Dyn : (A : Type) -> Type;
Dyn A = (n : Nat) -> A $ n;

Nat = n @-> (A : Type $ 0) -> A ->
true = x => y => x y;
false = y => x => y x;

weak = (n : Nat $ 1) => n () () (() => ());

|x|
t = A => (x : A) => x;

Fix = (x : Fix $ 0) -(0)> ()
fix = x => x x;


Double = (m : Nat $ 1) => (n : Nat, eq : m == n);

Bool = b @-> (A : Type $ 0) -> b Type |0 1 -> A;

Consume Only

Fix = (x : Fix $ 0) -(0)> ();
fix : Fix = x => x x;

Fix = (x : Fix $ 0) -> (() $ 0 -> ()) -> ();
fix : Fix = (x : Fix $ 0) => k => k (x x (() => ()));

False = (A : Type $ 0) -> A;
Fix = (x : Fix $ 0) -> (K : Type $ 0) -> ((False $ 0) -> K) -> K;
fix : Fix = (x : Fix $ 0) => k => k (x x False (f => f));

Fix = ∀(x : Fix). Π(k :(u : Unit). Unit). Unit;
fix : Fix = Λ(x : Fix). λk. k (x x (λu => u));

Fix = (x : Fix $ 0) -> ();
fix : Fix = x => x x;

main : (n : Nat $ 0) -> (() -> ()) $ n;

main2 = (n : Nat $ 0) -> (
  () = x;
  1
);

x @=> b => b _ (instance, x) None;

Nat = n @-> (P : Nat $ 0 -> Type $ 0) -> P zero ->
  ((pred : Nat $ 0) -> P pred -> P (succ pred)) $ n -> P n;
succ pred = n @=> P => z => s => s (pred P z s);


List(A : Type) : Type;
fold<A, K>(l : List(A), initial : K, f : A -> K -> K) : K;
length<A>(l : List(A)) : (List(A), Nat);


length(l) = fold(l, 0, x => (l, n) => (x :: l, 1 + n));


List(A) = (K : Type) -> K -> |A -> K -> K| -> K;
`A
~a

(x : Nat & x > 1) => _;
(x : Nat & x > 1) => _;
(x : Nat | x > 1) => _;
(x : Nat ~ x > 1) => _;

(x : ~Nat) => x;
(x : &Nat) => _;
(x : ^Nat) => x;
(x : 'Nat) => x;

List<A> = (K : Type) -> K -> |A -> K -> K| -> K;
length<A>(l : List<A>) -> (l : List<A>, s : Nat);
length<A>(l : &List<A>) -> Nat;

Bool : Type;
true : Bool;
false : Bool;

Bool = b @-> (P : Bool -> Type $ 0) -> |P true| -> |P false| -> |P b|;
true = P => then => |else| => then;
false = P => |then| => else => else;


case : &Bool -> (K : Type $ 0) -> |K| -> |K| -> |K|;

Fix = &Fix -> ();
fix : Fix = x => x;
x = (&b)


List<A : Type> : Type;
length<A>(l : List<A>) : (l : List<A>, s : Nat);
length<A>(l : &List<A>) : Nat;

length(l : List<A> $ 1) : Nat;



Bool = <A>(then : A, else : A) -> A;
true : Bool = _;
false : Bool = _;

clone(b : Bool) : (l : Bool, r : Bool) = b((true, true), (false, false));
weak(b : Bool) : Unit = b((), ());

Box<A> = <K>(with : A -> K) -> K;

Box<A> = <K>(with : A -> K) -> K;
&Box<A> = <K>(with : &A -> K) -> K;
borrow<A : Borrow, K>(box : Box<A>, k : &Box<A> -> K) : (box : Box<A>, k : K) =
  box(x => (
    k = k(with => with(x));
    (with => with(x), k);
  ));

Box = <K>(with : Socket -> K) -> K;
&Box = <K>(with : &Socket -> K) -> K;
borrow = <K>(box : Box, k : &Box -> K) : (box : Box, k : K) =>
  box(socket => (
    k = k(with => with(socket));
    (with => with(socket), k);
  ));
f = (box : &Box) => box((socket : &Socket) => _);

id
  : (A : Type $ 0) -> (x : A $ 1) -> A;
  = (A : Type $ 0) => (x : A $ 1) => x;

Socket : {
  send : (sock : Socket, message : String) -> (sock : Socket);
  close : (sock : Socket) -> ()
} = _;

Socket : {
  send : (sock : &Socket, message : String) -> ();
  close : (sock : Socket) -> ()
} = _;

List : {
  length<A>(l : &List<A>) : Nat;
} = _;

f = sock => (
  Socket.send(sock, "a");
  Socket.send(sock, "b");
  Socket.close(sock);
);

f = sock => (
  sock = Socket.send(sock, "a");
  Socket.send(sock, "b")
);



double = (x : Nat $ 1) => x + x;

Box<A> = <K>(with : A -> K) -> K;
&Box<A> = <K>(with : &A -> K) -> K;
borrow<A : Borrow, K>(box : Box<A>, k : &Box<A> -> K) : (box : Box<A>, k : K) =
  box(x => (
    k = k(with => with(x));
    (with => with(x), k);
  ));


make : (x : Int & x >= 0) => _;

Lifetime : Type;
zone<K>(k : <L>() -[L]> K) -> K;

borrow<L>(x : A) : &<L>A ! L;

Nat = n @-> (A : Type $ 0) -> A ->

(x : &Nat $ 1) => _;
&<L : Lifetime $ 0>(A : Type) : Type;

List<A : Type> : Type;
length<A>(l : List<A>) : (l : List<A>, s : Nat);

length<L, A>(l : &<L>(List<A>)) : Nat ! F<L>;

read(file : String) : String ! [IO];

read : (file : String) -[IO]> String;

<L>(x : &<L>Nat) : (L : Lifetime, (A : Type, x : A)) =>
  (L, (A = &<L>Nat, x));

add : <L_n : Lifetime $ 1, L_m : Lifetime $ 1>(n : Borrow<L_n>)

Box<A> = <K>(with : A -> K) -> K;
box<A>(x : A) : Box A = with => with(x);

Borrow<L, Box<A>> = <K>(with : Borrow<L, A> -> K) -> K;
borrow<A : Borrow, K>(box : Box<A>, k : <L>(box : &<L>Box<A>) -> K)
  : (box : Box<A>, k : K) =
  box(x => (
    k = k(with => with(x));
    (with => with(x), k);
  ));

(x : &<A>Int) =>

(fst : A, snd : fst == fst)
(fst : Type, snd : fst)


Bool : Type;
Null : Type;

(Int64 : Type) & {

} = _;

(Memory : Type) & {
  length(mem : Memory) : Int64;
  get(mem : Memory, addr : Int64 & addr < length(mem)) : Int64;
} = _;


C_bool = (A : Type) -> A -> A -> A;
I_bool(Bool : Type, true : Bool, false : Bool, b : Bool) =
  (P : Bool -> Type) -> P true -> P false -> P b;

I_unit(Unit : Type, unit : Unit, u : Unit) =
  (P : Unit -> Type) -> P unit -> P u;

Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : Unit -> Type) -> P unit -> P u;
unit = P => x => x;


Bool =


(Array(A : Type) : Type) & {

} = _;
Array(mem : Memory)


Pair mem = Int64

Nat = (z : Bool, s _ )



Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : Unit -> Type) -> P unit -> P u;
unit = P => x => x;


Unit : Type;
unit : Unit;

Unit = (u : Unit, i : (P : Unit -> Type) -> P unit -> P u);
unit = (unit, P => x => x);

ind : (u : Unit) -> (P : Unit -> Type) -> P unit -> P u
  = u => snd u : (P : Unit -> Type) -> P unit -> P (fst u);


(Int64 : Type) & {
} = _;

(Memory : Type) & {
  length(mem : &Memory) : Nat64;
  get(mem : &Memory, addr : Nat64 & addr < length(mem)) : Nat64;
} = _;

Ptr_type : {
  @Ptr_type(mem : &Memory, addr : Int64) -> Type
  size(mem : &Memory, addr : Int64) : Int64;
};

Word_size = 8;
Block(mem : &Memory, size : Nat64) =
  (addr : Int64 & addr + size < length(mem));
Usize(mem : &Memory) : Type = Block(mem, Word_size);

Ptr_type : {
  (mem : &Memory, addr : Int64) -> Type
  size(mem : &Memory, addr : Int64) : Int64;
};

Usize(mem : &Memory, addr : Int64) : Type = addr + Word_size < length(mem);
Pair(L : Ptr_type, R : Ptr_type)(mem : Memory, addr : Int64) : Type =
  (l : L(mem, addr))

Usize = {
  *<mem>(size : )
};

String(mem : &Memory) =
  (len : Usize(mem)) & Block(mem, *len);


Pair(mem : Memory, L : Type, R : Type) =
  (addr : Int64, addr < length(mem), )






Bool : (A : Type) -> A -> A -> A;

x @=> x; // negative?
x @=> y => x; // negative?

(@x : T) @=> b => b T (Some (1, x)) None;

(@x : T) @=> b => b T (Some (1, x)) None;

Nat = (A : Type) -> A -> (Nat -> A) -> A;
Nat = n @-> (P : Nat -> Type) -> P zero -> ((pred : Nat) -> P (succ pred)) -> P n;

Bool : Type;
true : Bool;
false : Bool;

Bool = b @-> (P : Bool ∞ $ 0 -> Type) -> P (true) -> P (false) -> P (b ∞);

Nat = n @-> (P : Nat ∞ $ 0 -> Type) ->
  P zero -> ((pred : Nat) -> P (succ pred)) -> P n;

Nat = n @-> (A : Type) -> A -> ((pred : Nat) -> n = succ pred -> A) -> A;

sized(n : Nat)(fold) @=>
  A => z => s => n A z (pred => lower => s (fold pred lower A z s));

fold = (fold : (n : Nat) -> (A : Type) -> A -> (A -> A) -> A) @=>
  n => A => z => s => n A z (pred => s (fold pred A z s));

fold = (fold : (n : Nat) -> (A : Type) -> A -> (A -> A) -> A) @=>
  n => A => z => s => n A z (pred => s (fold A z ));

Pair(A : Type, B : Type) =
  (K : Type $ 0) -> |A -> B -> K| -> K;


id : (A : Type) -> (x : A) -> A
  = (A : Type) => (x : A) => x;

y = id(String);
x = id(Nat)(1);

f = x => x;
x => y => y x;
x => y => x y;
x => y => x;
x => y => y;
x => x + x;

Socket : {
  connect : () -> Socket;
  send : (sock : &Socket, msg : String) -> ();
  close : (sock : Socket) -> ();
} = _;

(sock : Socket) => (
  Socket.send(sock, "hi");
  Socket.close(sock);
  1
);

Memory : {
  malloc : (size : Nat) -> Memory;
  free : (mem : Memory) -> ();
} = _;

Omega = (x => x x) (x => x x);

(x => x x) (x => x x)
(x => x x) (x => x x)

Nat = n @-> (P : Nat -> Type) ->
  |P zero| -> |(pred : Nat) -> P (succ pred)| -> P n;

sized(n : Nat)(fold) @=>
  A => z => s => n A z (pred => lower => s (fold pred lower A z s));

sized(size : (x : T) -> Nat))(fold : (y : T) -> size x = succ (size y) -> K) @=> _;


Bool : Type;
true : Bool;
false : Bool;

Bool = b @-> (P : Bool -> Type) -> P true -> P false -> P b;


Nat = (P : Nat -> Type)

False = (A : Type) -> A;
Fix = (x : Fix) -> False;

fix : Fix = (x : Fix) => x x;
omega = fix(fix);

(x => x x)(x => x x);

Term =
  | x
  | x => M
  | M N;

(x => M) N === M[x := N];


(x => x x) (x => x x)
(x x)[x := (x => x x)]
(x => x x) (x => x x)

((x => x) 1)

(Int -> Fix Int)


(x => x + x) 1 === (x + x)

(x => x x) (x => x x);


Bool : Type;
true : Bool;
false : Bool;

Bool = b @-> (P : Bool -> Type) -> P true -> P false -> P b;
true = P => x => y => x;
false = P => x => y => y;


Nat : Type;
zero : Nat;
succ(pred : Nat) : Nat;

Nat = n @-> (P : Nat -> Type) -> P zero ->
  ((pred : Nat) -> n = succ pred -> P (succ pred)) -> A;




Unit (i : Size) : Type;
unit (i : Size) : Unit;
Unit i = u @-> (P : (u : Unit i) -> Type) -> P (unit i) ->


Unit (i : Size) : Type;
unit (i : Size) : Unit i;

Unit α = u @-> (P : ((β : Size < α) -> Unit β) -> Type) ->
  P (β => unit β) -> P (β => u β);

unit α = P => x => x;

Unit : Type;
unit : Unit;

Unit = (α : Size) -> Unit α;
unit = (α : Size) => unit α;

ind : (u : Unit) -> (P : Unit -> Type) -> P unit -> P u;
  = u => P => x => u 0 (β => P )
fold (u : Unit) = A => x =>


(u : Unit)

Size = (A : Type) -> (A -> A) -> A;
next (s : Size) = A => n => n (s A n);
le : (α : Size) -> (β : Size) -> Type;

Nat : (β : Size) -> le β α -> Type

(Nat [α]) @=>
  (A : Type) -> A -> ((β : Size) -> (lower : le β α) -> Nat β lower -> A) -> A;



Size = (A : Type) -> (Size -> A) -> A;

Size (i : Size i) : Type;

Size α = s @-> (A : Type) -> ()

fold : (n : Nat) -> (A : Type) -> A -> (A -> A) -> A;
sized(fold, n) @=> A => z => s =>
  n A z (pred => lower => fold pred lower A z s);


x @=> x

Nat @=> (A : Type) -> A -> (Nat -> A) -> A;

Nat @=> n @-> (P : Nat -> Type) -> P zero ->
  ((pred : Nat $ 0) -> P pred -> P (succ pred)) $ n -> P n;

Nat @=> (A : Type) -> A -> (A -> A) -> A;


[@teika.core.ir]


Fix = Fix -> ();
fix : Fix = (fix) -> clone(fix)(fix)

borrow : &<L>T $ n;

Size = (A : Type) -> (A -> A) -> A;
next (i : Size) = A => s => s (i A s);


Nat (i : Size) : Type;
Nat α = n @-> (A : Type) -> A ->
  ((β : Size) -> (pred : Nat) -> A) -> A;


fold [s] (n : Nat) = A => z => s =>
  n A z (pred => lower => s (fold pred lower A z s));


Unit (α : Size) : Type;
unit (α : Size) : Unit α;

Unit α = u @-> (P : ((β : Size) -> β < α -> Unit β) -> Type) ->
  (P (β => lower => unit β)) -> (P (β => lower => u β));
unit α = P => x => x;


Unit = (α : Size) -> Unit α;
unit = (α : Size) => unit α;


Nat (i : Size) : Type;
Nat α = n @-> (P : ((β : Size < α) -> Unit β) -> Type) ->
  P (β => unit β) -> P (β => u β);

unit α = P => x => x;

Nat α = n @-> (A : Type) -> A -> ((β : Size) -> α < β -> Nat β -> A) -> A;

fold α = n => A => z => s
  n A z (fold (β => lower => pred => fold β lower pred A z s));

(@Unit : Type) @=> (u : Unit) @-> (P : Unit -> Type) ->
  P ((u : Unit) @=> P => x => x) -> P u;

@((Unit : Unit @-> Type) @=> I => u @->
  (P : @Unit I -> Type) -> P (I unit) -> P (I u)) (refl);

(Unit : Unit @-> Type) @=> I => u @->
  (P : @Unit I -> Type) -> P (@I unit) -> P (@I u)

(@T_False : Type) @=>
  (@False : T_False) @->
    (f : @((@T_f : Type) @=> ((f : T_f) @-> False f))) -> Type;







(@Unit : Unit) @-> Type;

(False) : Type -> Type;


(Unit ) @=>
  I => u @-> (P : @Unit I -> Type) ->
    P (u @=> P => x => x) -> P u;
()
unit : @Unit;

@unit
expected @Unit

received : (P : @Unit -> Type) -> P u -> P u;
expected : @Unit

received : @Unit
expected : @Unit


@Unit = (@Unit : Type) @=> @(u : Unit) @->
  (P : Unit -> Type) -> P (@(u : Unit) @=> P => x => x) -> P (@fold u);

(@T : ) @-> (I : I @-> @T I -> Unit) -> Type;

(I : (I : T_I) @-> @T I -> Unit) -> Type
x : (P : Unit -> Type) -> P unit -> P x;
fold x : @u @-> (P : Unit -> Type) -> P unit -> P (@fold u);

(@T_False : Type) @=>
  (@(False : T_False) @-> )
unit = _;


@x : (P : Unit -> Type) -> P unit -> P (@unit)
@u

Γ, x : A |- B : Type
-----------------------------
Γ |- @assume(x : A). B : Type

Γ, x : A |- B : Type  Γ, x : A |- M : B
---------------------------------------
Γ |- @fix(x : A). M : @assume(x : A). B

Γ, x : A |- B : Type
----------------------------
Γ |- @self(x : A). B : Type

Γ |- M : @assume(x : A). B  Γ |- AB
--------------------------------------
Γ |- @verify M : @self(x : A). B

Γ |- M : @self(x : T). T
--------------------------
Γ |- @unroll M : B[x := M]


Unit : @assume(@Unit : Type). Type
  = @fix(@Unit : Type). @self(u : Unit). (P : Unit -> Type) -> P u -> P u;
Unit : @self(@Unit : Type). Type = @verify Unit;
Unit : Type = @unroll Unit;

unit : @assume(u : Unit). (P : Unit -> Type) -> P u -> P u
  = @fix(u : Unit). P => x => x;
unit : @self(u : Unit). (P : Unit -> Type) -> P u -> P u = @verify unit;
unit : Unit = unit;


T = Unit @-> (I : I @-> @Unit I -> !Unit) -> Type;

@fix(@T_Unit : Type). @self(Unit : T_Unit).
  (I : @fix(T_I : Type). @self(I : T_I). ) -> Type;

Unit : @assume(@Unit : Type)

unit : @assume(u : Unit). (P : Unit -> Type) -> P u -> P u
  = @fix(u : Unit). (P : Unit -> Type) => (x : P u) => x;
unit = @verify()

Unit = @self(u : Unit). (P : Unit -> Type) -> P u -> P u;

@Unit = @verify Unit;

@fix(@u : Unit)
Nat = @fix(@Nat : Type). (A : Type) -> A -> (Nat -> A) -> A;
Nat = @verify Nat;


Unit = @fix(@Unit : Type). @self(u : Unit). (P : Unit -> Type) -> P u -> P u;
@Unit = @verify Unit;

unit = @fix(@u : Unit). (P : Unit -> Type) => (x : P u) => x;

@self(u : Unit). (P : Unit -> Type) -> P u -> P u

Nat_T = @assume(Nat : Type). Type;

@fix(Nat) : Type = (A : Type) -> A -> (@unroll Nat -> A) -> A;

@assume(@False) : Type. Type;

False = @fix(@False : Type). @self(f : False). (P : False -> Type). P f;
False = @verify(False);

@fix(@Unit) : Type. @self(u : Unit).
  (P : Unit -> Type) -> P


Γ, x : A |- M : A
----------------------
Γ |- @fix(x) : A. M :

Γ, x : A |- B : Type
--------------------------------
Γ |- @fix(x : A). B : Self


@fix(False) : Type.
  (P : @unroll False -> Type) ->

@fix(Unit) : Type.
  (P : @unroll Unit -> Unit) -> P


unit : @self.open(u : Unit). (P : Unit -> Type) -> P unit -> P u;



False = @self(f : @self.close False). (P : @self.close False -> Type) -> P f);
False = @self.close False;


Bool : Type;
true : Bool;
false : Bool;

Bool = @self(b : Bool). (P : Bool -> Type) -> P true -> P false -> P b;
true = P => x => y => x;
false = P => x => y => y;



Γ, x : A |- B : Type
----------------------------
Γ |- @self(x : A). B : Type

Γ, x : A |- B : Type  Γ, x : A |- M : B
---------------------------------------
Γ |- @fix(x : A). M : @self(x : A). B

Γ |- M : @self(x : A). B  Γ |- A ≂ @self(x : A). B
--------------------------------------------------
Γ |- @unroll M : B[x := M]

Γ |- T : Type  Γ, x : T |- M : T
-------------------------------- // TODO: avoid this
Γ |- @fix(@x : T). M : T


T_False = False @-> (f : f @-> @False f) -> Type;

T_False : Type;
T_f : (False : T_False) -> Type;

T_False = @self(False : T_False). (f : T_f False) -> Type;
T_f = False => @self(f : T_f). @False f;


T_False = @fix(@T_False).
  (T_f : @fix(@TT_f). @self(T_f : TT_f). (False : T_False T_f) -> Type)) => (
  T_False = T_False T_f;
  T_f = @T_f;
  @self(False : T_False). (f : T_f False) -> Type;
);
T_f = @fix(@T_f). (
  T_False = T_False T_f;
  False => @self(f : T_f). @False f
);

T_False (T_f : Type) = @fix(@T_False).
  @self(False : T_False). (f : T_f) -> Type;
T_f = @fix(@T_f). (False : T_False T_f) =>
  @self(f : T_f). @False f;

@fix(@F_False : Type).
  @self(False : F_False).

@self(T_f). @self(f : T_false T_f). @False f

T_False = @fix(@T_False). (T_f : Type) =>
  @self(False : T_False T_f). (f : T_f) -> Type;
T_f = @fix(@T_f). (False : T_False T_f) => @self(f : T_f False). @False f;

@fix(@T_False2). T_False (T_f T_false2)

Unit = @fix(@Unit : )


Bool : Type;
true : Bool;
false : Bool;

Bool = @self(b : Bool). (P : Bool -> Type) -> P true -> P false -> P b;
true = P => x => y => x;
false = P => x => y => y;



Unit = @fix(Unit). unit => @self(u : @Unit unit).
  (P : @Unit unit -> Type) -> P @unit -> P u;
unit = @fix(unit). @fix(u : @Unit unit). P => x => x;

(P : Unit -> Type) -> P (@fix(u : Unit). P => x => x) -> P u

expected : @self(u : Unit). (P : Unit -> Type) -> P unit -> P u;
received : @self(u : Unit). (P : Unit -> Type) -> P u -> P u;

(u : Unit) => @u

unit : Unit = @fix(u : Unit). P => x => x;


unit : _ = _;

Unit = @Unit unit;
unit = @unit;

unit = @fix(u). P => x => x;



T_False = False @-> (f : f @-> @False f) -> Type;

T_False : Type;
T_f : (False : T_False) -> Type;

T_False = @self(False : T_False). (f : T_f False) -> Type;
T_f = False => @self(f : T_f). @False f;


T_False = @fix(T_False). T_f => (
  T_False : Type = @T_False T_f;
  T_False : (False : T_False) -> Type = @T_f;
  @self(False : T_False). (f : T_f False) -> Type;
);

T_False = False @-> (f : f @-> @False f) -> Type;
T_False = @fix(@T_False : Type).
  @self(False : T_False). (f : @self(f : ?) -> @False f) -> Type;

T_False = (T_f : Type) -> @fix(@T_false : Type).
  @self(False : T_false). (f : T_f) -> Type;
T_f = (False : T_False) => @fix(@T_f : Type).
  @self(f : T_f). @(False T_f) f;

False : T_False = T_f => @fix(False : @self(False : T_false). (f : T_f) -> Type).
  (f : T_f) =>
  ()

Unit = @self(Unit : T_unit). (unit : @self(unit : Unit). @Unit unit) -> Type
Unit = @fix(Unit : Type).

T_False = False @-> (f : f @-> @False f) -> Type;

T_False : Type;
T_f : (False : T_False) -> Type;

T_False = @self(False : T_False). (f : T_f False) -> Type;
T_f = False => @self(f : T_f False). @False f;


T_False = @fix(@T_False : Type). (
  T_f = @fix(T_f). (
    T_False = @self(False : T_False). (f : @T_f False) -> Type;
    False => @self(f : T_f False). @False f
  );
  T_f = @

  @self(False : T_False). (f : T_f False) -> Type;
);

Γ, x : A |- B : Type
---------------------------
Γ |- @self(x : A). B : Type

Γ |- M : @self(x : A). B  Γ |- A ≂ @self(x : A). B
--------------------------------------------------
Γ |- @verify M : A

Γ |- M : @self(x : A). B  Γ |- A ≂ @self(x : A). B
--------------------------------------------------
Γ |- @unroll M : B[x := M]


Γ
False


------------
Γ |- A $ n : Type
(f : Int $ 0) -> (x : Nat)

(x : Int $ 1) => x;

f : (x : Nat & x <= 5) -> _;

(x : Nat) => (x_le_5 : x <= 5) => _;

(A : *) -> (x : A) -> A;
(A : Type) -> (x : A) -> A;


Type @->

Type @=> forall =>
Type : Type @-> @Type = Type @=> @Type;
Id : @Type = (A : @Type) -> A;

@Type : Type;
@(->) : (A : Type) -> (B : (x : A) -> Type) -> Type;
@(=>) : (A : Type) -> (B : (x : A) -> Type) -> (M : (x : A) -> B x) -> Type;

Type = Type;
(->) A B =


(Type : Type @-> @Type) =>



(Type : Type @-> Type) =>


(A : Type $ 0) =


// TODO: is this valid?
(x : P (x => Type)) => _


-----------



String : Type;
Type : Type;


((x : String) -> String);

T : Type = (A : Type) -> (x : A) -> A;
f : (A : Type) -> (x : A) -> A = _;

(f String) : (x : String) -> String;

Type : Type

((A : Type) -> (x : A) -> A) : Prop


Type : Kind
Kind : Δ

Set of all sets that doesn't include themselves

Nat : Type 0

Type : Type


Type 0 : Type 1
Type 1 : Type 2
Type n : Type (1 + n)

Type : Type


Nat =
  | Zero
  | Succ (pred : Nat);


Nat0 = (A : Type) -> (zero : A) -> A;
Nat1 = (A : Type) -> (zero : A) -> (succ : (pred : Nat0) -> A) -> A;
Nat2 = (A : Type) -> (zero : A) -> (succ : (pred : Nat1) -> A) -> A;

@Nat : Type = (A : Type) -> (zero : A) -> (succ : (pred : Nat) -> A) -> A;
@fold (n : Nat) (A : Type) (acc : A) (f : A -> A) : A =
  n A acc (pred => f (fold pred A z f));

(x => x x) (x => x x)

Nat (α : Size) = (A : Type) -> (zero : A) ->
  (succ : (β : Size) -> β < α -> (pred : Nat β) -> A) -> A;

@fold [α] (n : Nat α) (A : Type) (acc : A) (f : A -> A) : A =
  n A acc (β => lower => pred => fold β lower pred A (f acc) f)

Γ, α : Size |- T : Type
Γ, α : Size, x : (β : Size $ 0) -> β < α -> T |- M : T
--------------------------------------------------
Γ |- @fix(x [α] : T). M

f : (x : A) ->? B
f : (x : A) -> B


Type 0 : Type 1
Type 1 : Type 2


Nat = n @-> (A : Type) -> A -> (A -> A) $ n -> A;
List A = l @-> (K : Type) -> K -> (A -> K -> K) $ length l -> K;

O(length l)

Nat (α : Size) = (A : Type) -> (zero : A) ->
  (succ : (β : Size) -> α = 1 + β -> (pred : Nat β) -> A) -> A;


Nat = (A : Type) -> A -> (Nat -> A) -> A;

Nat (mem : Memory) = (addr : Pointer & addr | 0 => _ | _ => )

Performance = _;
Proof = _;
Utils = _;

pred : (s : Size) -> Nat s -> Nat s;

pred : Nat -> Nat;

Nat : Type 1 = (l : Level $ 0) -> (A : Type l) -> A -> (A -> A) -> A;


// fold : (β : Size) -> β < α -> (n : Nat β) -> (A : Type) -> (acc : A) -> (f : A -> A) -> A
f : (x : -A) -> +B = _;

-(int list) +(string list) +int

Nat =

Id0 : Type 1 = (A : Type 0) -> A -> A;
id0 : Id0 = A => x => x;

Id1 : Type 2 = (A : Type 1) -> A -> A;
id1 : Id1 = A => x => x;

id1 Id0 id0


(x : P (x => Type)) => _

Nat = n @->


Γ, x : T $ n |- M : T
-----------------------------------
Γ |- @fix(x : T $ 1 + n). M : T


Nat : Type;
(0) : Nat;
(1 +) : (pred : Nat) -> Nat;

Nat = n @-> (P : Nat $ 0 -> Type $ 0) ->
  P 0 -> ((pred : Nat) -> P (1 + pred)) -> P n;
(0) = P => z => s => z;
(1 +) pred = A => z => s => s pred;


Nat = n @-> (A : Type) -> A -> (A -> A) $ n -> A;

n => @fix(fold $ 1 + n).
  A => acc => map => n A acc map;

(n : Nat) => (A : Type) => (acc : A) => =>
  @fix(fold $ 1 + n). (n_ == n) =>
  (A : Type) => (acc : A) => (map : A -> A) =>
    n_ (_ => A) acc (pred => fold )

(n : Nat) =>
double (n : Nat) =
  n Nat (0, 0) ()

is_even = (n : Nat) =>
  n Bool true (@fix(not : Bool -> Bool $ 1 + n). b)


(x : A) => M
(x : P (x => Type)) => _;





2

x => y => (x y)[swap]
x => y => (y => x => x y) y x

(1)[x => x Int String]


(x : (A) $ b) => _

(x: A) (:) (A : Type)

T = A $ 5;

(A : Type : ) -> A -> A;

Type : Type;
Value : Type;
Prop : Type;

(A : Type) -> (x : A) -> A

Univ : Univ; // erasable
Prop : Univ; // irrelevant
Type : Univ; // relevant
// TODO: parametric

Γ $ 0 |- M : Univ
---------------------
Γ $ 0 |- @squash M : Type

(Γ, x : A) $ 0 |- B : Type
----------------------------
Γ $ 0 |- (x : A) -> B : Type

Γ $ 0 |- A : Univ  Γ, x : A $ ∞ |- M : B
----------------------------------------
Γ |- (x : A) => M : (x : A) -> B

Γ $ 0 |- A : Type  Γ, x : A $ 1 |- M : B
----------------------------------------
Γ |- (x : A) => M : (x : A) -> B

Γ |- M : (x : A) -> B  Γ |- N : A
---------------------------------
Γ, Δ |- M N : B[x := N]

((x $ 0) : A) ->
((x : A) $ 0)
(x : (A $ 0))
(f : A -> B)
f : A $ 0

(f : A $ 0 : Univ) ->

Fix = Fix -> Type;
(x : Fix) => x x;



Type : (n : Nat) -> Type 0;

((x : A) -> B) : Type 2

(A : Type 1 : Type 0) => (x : A : Type 1) -> x;

(A : Type 2) => (x : A) => (x, x);
(A : Type $ 0) => (x : A $ 2) => (x, x);


(A : Type) => (x : A $ 2) => x


Kind =
  | Erasable
  | Irrelevant
  | Multiplicative
Type : ()

Type : Type
Linear : Type

Type : Univ
Type : Type

(A : Linear)

((x : A) $ G)

(x : ) : Promise<T, E> => _


malloc : () -> (L : Lifetime);
free : (L : Lifetime) -> ();


lifetime : <A>(x : &A) -> Lifetime;

() -[Allocator Root]> ()
() -[Allocator One]> ()

add : (x : &Nat, y : &Nat) -> Nat;
add : (x : &Nat, y : &Nat) -[Borrow x | Borrow y]> Nat;

add : (x : &Nat, y : &Nat) -> Nat;

<L>(x : &<L>Nat) =[Zone L]> x + x;

(x : &Nat) =[Zone x]> x + x;

(x : &Nat) => (
  (x1, x2) = x.copy()
  (x1, x2)
)

Type : Univ;
Prop : Univ;

f = (A : Type : Univ) => (x : A : Type) => x;

(A : Prop : Univ) => (x : A : Prop) => _;

borrow : <K>(x : Nat, region : () -[Zone x]> K) -> K;


Type 0 : Type 1
Prop : Type 0

SFalse : Prop = (A : Prop) -> A;
False : Type = (A : Type) -> A;

f : SFalse -> False = _;

Unit : Prop = (A : Prop) -> A -> A;

(A : Type 0) => (u : Unit) => u (Type 0) A

Bool : Prop = (A : Prop) -> A -> A -> A;

(b : Bool) => b (Type 0)
(A : Type) => (x : (A : Prop) -> Prop) => x;


Fix : Type;
&Fix : Type;

Fix = &Fix -> A;
&Fix = &Fix -> A;


@Fix = f @-> (P : Fix -> Type) -> (x : Fix) -> P x -> P f;

Fix : Type;
fix : Fix;

Fix = (x : Fix) -> ();
fix = x => fix x;

&Fix : Type;
fix : Fix;

Fix = f @-> (P : Fix -> Type) -> P fix -> &Fix -> P f;
&Fix = f @-> (P : &Fix -> Type) -> P (&fix) -> &Fix -> P f;

fix = P => p_fix => x => x P p_fix x;

Type : Type;
Data : Type; // clonable?
Prop : Type;

Typed Tree's

Checking Compiling Hover on Type Typer tracking Partial rebuild Debugging Jump to definition Serialization

Macabas

do {
  const x = 1;
  return x + 1;
}

(let x = 1; x + 1)
(x = 1; x + 1)

x => (
  y = (
    z = x;
    x + 1
  );
  y + 2;
);


----------------
Γ |- Type : Type

Γ |- A : Type  Γ, x : A |- B : Type
-----------------------------------
Γ |- (x : A) -> B : Type

Γ, x : A |- M : B
--------------------------------
Γ |- (x : A) => M : (x : A) -> B

Γ |- M : (x : A) -> B  Γ |- N : A
---------------------------------
Γ |- M N : B[x := N]



clone : (x : Nat) -> (l : Nat, r : Nat) = _;

Array : {
  get : <A>(arr : &Array A, i : Nat) -> (el : A);
  set : <A>(arr : Array A, i : Nat, el : A) -> (arr : Array A);
  size : <A>(arr : &Array A) -> (size : Nat);
} = _;



x[0] := x;

double = (x : &Nat) => x + x;
double = (x : &Nat $ 2) => x + x;

id = (A : Type $ 0) => (x : A) => x;

f = (x : Nat) => (x_le_5 : x <= 5) => x;

Unit =
  | unit;

f = (n : Nat) => (x : Unit) => n;

(n : Nat) => (x : Unit) => (y : Unit) : Eq(f n x, f n y) => ()

f n unit == f n unit

Eq<A>(x : A, y : A) =
  | refl : Eq(x, x);

refl

Erasable
Irrelevance
Duplicable / Multiplicative


Type : Univ;
Data : Type;
Prop : Data;

(A : Type : Univ) => (x : A : Type) => x;
(A : Prop : Type) => (x : A : Prop) => x;
(A : Data : Type) => (x : A : Data) => (x, x);

(A : Type) => (x : A) => x;
(A : Prop) => (x : A) => x;
(A : Data) => (x : A) => (x, x);


<A : Type>(x : A) => x;
<A : Prop>(x : A) => x;
<A : Data>(x : A) => (x, x);


<A>(x : A) => x;
<A>(x : Prop A) => x;
<A>(x : Data A) => (x, x);

Box (A : Type) : Data;

Eq<A : Type>(x : A, y : A) =
  | refl : Eq(x, x);

(A : Data) => (x : A) => (eq : Eq(x, x)) : Eq(eq, refl) => _;

Eq(1, 2) : Prop;


f = (x : Nat, y : Float) -> String;


Box (A : Type) = <R>(k : (x : A) -> R) -> R;

Box<M>(A : Type) = <R>(k : (x : M A) -> R) -> R;
Box<K>(A : K) = <R : K>(k : (x : A) -> R) -> R;

(A : Type) => (x : Prop A) => x;

(A : Type) => (x : Box<Prop> Unit) => x



(x )

Type : Univ;
Data : Univ;
Prop : Univ;

Nat : Type = Prop Nat;
(x : Nat) =>

Box (T : Type) = <A>(k : T -> A) -> A;

Box<K>(T : K) : K = <A : K>(k : T -> A) -> A;
Box() : Prop
Box (Eq(1, 2)) : Prop;

Box(A : Type) : Type = <A>(k : T -> A) -> A;

(A : Type) => (x : Prop (Box A)) => x

(A : Prop) => (x : Box A) => x

(A : Type) => (x : Data Nat) => (x, x);

(+) : (x : &Nat) -> (y : &Nat) -> Nat;
(x : Data Nat) => x + x;

(x : &Nat) => (x, x);

Kind : Kind; // universes, erasable
Type : Kind; // resources, linear
Data : Kind; // data, duplicable
Prop : Kind; // propositions, irrelevant

Box (A : Type) = <K>(k : (x : A) -> K) -> K;

(A : Type) => (x : A) =>
(A : Type)

List(A : Type) : Type;
List(A : Data) : Data;
List(A : Prop) : Prop;

Squash (K : Kind) : Type = <A>(K -> A) -> A;
squash<K>(x : K) : Squash K = k => k x;


id = (A : Type) => (x : A) => x;
id (squash Type) : (x : squash Type) -> squash Type;

Eq<A : Type>(x : A, y : A) : Type;
Eq<A : Data>(x : A, y : A) : Prop;

List(A : Type) : Type;


List<K>(A : K) : K;

(x : &Nat) =>

Kind : Kind; // universes, erasable
Type : Kind; // resources, linear
Data : Kind; // data, duplicable
Prop : Kind; // propositions, irrelevant

// TODO: functions over data, can they be in Data? What about h-sets?
// TODO: functions over data also implies in automatic memory management

List(A : Type) : Type;
Double(A : Type) = (x : A, y : A)



b @-> (P : Bool -> Type) -> P true -> P false -> P b


x : Type = (A : Data) -> A;

Fix = f @=>


User : Type + Copy + Free;

(A : Type & A = Prop _) =>


Kind : Kind; // universes, erasable
Type : Kind; // resources, linear
Data : Kind; // data, duplicable
Prop : Kind; // propositions, irrelevant

// functions on data? Maybe make it predicative?
// functions on prop?

False : Type = (A : Data) -> A;

f = (A : Data) => (x : A) => x;
(A : Data) => (x : A) => x
Nat64 : Data;
Nat64.size = 8;

Pointer(mem : Memory, size : Nat64) : Data;
Pointer(mem, size) = {
  addr : Nat64;
  valid : addr + size < length(mem);
};

Nat128(mem : Memory) : Data;
Nat128.size : Nat64;

Nat128(mem) = Pointer(mem, Nat128.size)
Nat128.size = 16;

String(mem) : Data;
String.size(mem) : Nat64;

String(mem) = {
  addr : Nat64;
  valid : addr + Nat64.size + String.size(mem) < length(mem)
};

User(mem) : Data;
User(mem) = {
  addr : Nat64;
  valid : addr + Nat128.size + ;
};

LSP Flow

External Message -> Check State -> Queue Message
                                -> Error

Queue Message -> Lock Required Data -> Compute -> Commit Change ->

Self Type

T_False = Unit @-> Type;
(False : T_False) @=> f @-> (P : False -> Type) -> P f;

False : Type) @=> f @-> (P : False -> Type) -> P f;

Unit = u @-> (P : Unit -> Type) -> P unit -> P u;

@Unit : Type;
@unit : Unit;

@Unit = (u : Unit) @-> (P : Unit -> Type) -> P unit -> p u;
@unit = P => x => x;


False : (False : Type) -> Type
  = (False : Type) => (f : False) @-> (P : False -> Type) -> P f;
False : Type = @tie(False);


T_False = False @-> (f : f @-> @False f) -> Type;

T_False : Type;
T_f : (False : T_False) -> Type;

T_False = (False : T_False) @-> (f : T_f False) -> Type;
T_f False = (f : T_f False) @-> @False f;



T_False = (T_False : Type) => (T_f : (False : Type) Type) => (f : T_f) -> Type;

T_Unit = (T_Unit : Type) => (Unit : T_Unit) ->
  (unit : @tie((T_unit : Type) => Unit )) -> Type;

Unit : (Unit : Type) -> (unit : Unit) -> Type
  = (Unit : Type) => (unit : Unit) =>
      (u : Unit) @-> (P : Unit -> Type) -> P unit -> P u;

Unit = @fix(Unit)
T_Unit = Unit @->

T_False = False @-> (f : f @-> @False f) -> Type;

((@T_False : Type) @=>
  (False : T_False) @-> (f : ) -> Type);

(T_False) : Type @=>


Unit : Type;
unit : Unit;

Unit = (u : Unit) @-> (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;

T_False = False @-> (f : f @-> @False f) -> Type;

T_False : Type;
T_f : (False : T_False) -> Type;

T_False = (False : T_False) @-> (f : T_f False) -> Type;
T_f False = (f : T_f False) @-> @False f;

T_False = False @-> (I : I @-> _ -> @False I) -> Type;

@tie(T_False : Type, T_f : (False : T_False) -> Type). (
  T_False1 = (False : T_False) @-> (f : T_f False) -> Type,
  T_f1 (False : T_False1) = (f : T_f False) @-> @False f
)



@fix.self()



Kind : Kind; // not h-set, affine, erasable
Type : Kind; // not h-set, linear, managed manually
Data : Kind; // h-sets, intuitionistic, reference counted
Prop : Kind; // h-sets, intuitionistic, irrelevant


Bool = (A : Type) -> |A| -> |A| -> A;

clone
Fast : Kind; //

[@teika.mode.performance]
(A : Data) => (x : A) => (x.clone(), x)

Smol CPS

RC Smol

id = (A : Data) => (x : A) => (x, x);
id = (A : Type) => (x : A) => x;

GC Minor + Rc Major

x = 1;
x = x + 1;
y = x + 2;

Kind : Kind; // not h-set, affine, erasable
Type : Kind; // not h-set, linear, managed manually
Data : Kind; // h-sets, intuitionistic, reference counted
Prop : Kind; // h-sets, intuitionistic, irrelevant



Γ |- A : P  Γ, x : A |- B : R
-----------------------------
Γ |- (x : A) -> B : K

{ P : 'P; R : Type; K : Type }
{ P : 'P; R : Prop; K : Prop }
{ P : Type; R : Data; K : Type } // prevent linear violation
{ P : Data; R : Data; K : Data }
{ P : Prop; R : Data; K : Data }


Unit : Prop;

id = (x : Unit) => id;
Fix : Type = Fix -> Unit;
fix = x => id (x x);

id : (A : Type) -> (x : A) -> A = _;

(A : Type) => (x : A) => x

((x : A : Type) -> (B : Data)) : Type
((x : A : Prop) -> (B : Data)) : Data
((x : A : Data) -> (B : Data)) : Data

((x : A : Type) -> (B : Prop)) : Prop

(x : A : Type 0) => (A : Prop) => (x : A) => x

()

@tie()
@fix
(x : )

Erasing Kinding System

Type : Kind;
Data : Kind;
Prop : Kind;


Sigma A B =
  s @-> (P : Sigma A B -> Type) ->
    ((fst : A) -> (snd : B fst) -> K) -> P s;
Prop = p @-> (P : Prop -> Type) ->
    ((A : Type) -> (x : A) -> (irr : (y : A) -> Eq x y) -> P _)
  -> P p;
Prop = (A : Type, x : A, )
Data = (A : Type, x : Rc A);

(A : Data) => (x : fst A) => _
Kind.free<A : Kind>(x : A) : n

Unit : Type;
unit : Unit;

Unit = u @-> (P : Unit -> Type : Kind) -> P unit -> P u;


Type : Erasable Type;

Bool = (A : Type) -> A -> A -> A;
(b : Bool) => (b (@squash Type) : @squash Type -> @squash Type : Type)
(b : Bool) => (@unsquash (b (@squash Type)) : Type -> Type : Kind)


Type : Type;

Fix = Fix -> Type;
fix = x => x;

LType : LType;
IType l : IType (l + 1);

id = x => x;

fix = x => x x;
omega = fix fix;

Type : Type;

Fix = Fix -> ();
fix : |Fix| = x => x x;

(x) => x + x


Fix = Fix -> ();

Nat [a] = (K : Type) -> K -> ((b < a) -> Nat b -> K) -> K;
fold [a] = (n : Nat [a]) => K => acc => f =>
  n K acc (b => pred => fold [b] pred K (f acc) f);

Type : Type;


Term [a] = (K : Type) ->
  (var : String) ->
  (app : [l] -> [r] -> a == 1 + l + r -> Term [l] -> Term [r] -> K) ->
  (abs : [b] -> a == 1 + b -> String -> Term [b] -> K) ->
  K;

Term [a] = (K : Type) ->
  (var : String -> K) ->
  (app : [l] -> [r] -> a == 1 + l + r -> Term [l] -> Term [r] -> K) ->
  (abs : [b] -> a == 1 + b -> String -> Term [b] -> K) ->
  K;

abs "x" (var "x")
(x => x)

[s_f] => [s_x] => (f : T [s_f]) => (x : _) => x y



size M = a
size N = b
M N =

app lambda arg : Term = K => app => abs => app lambda arg;
abs body : Term = K => app => abs => abs body;

id : Term = abs (x => x);

Type [α] : Type [1 + α]

// template

Γ |- n : Size  Γ |- A : Type n  Γ |- M : A
------------------------------------------
Γ |- M : A

// size

-----------------
Γ |- Size : USize

-------------
Γ |- 0 : Size

Γ |- n : Size
-----------------
Γ |- 1 + n : Size

// universe

Γ |- n : Size
--------------------
Γ |- Type n : Type 0

//

Γ, n : Size |- T : Type m
---------------------------------------
Γ |- (n : Size) -> T : Type (m[n := 0])

Γ, n : Size |- M : T
--------------------------------------
Γ |- (n : Size) => M : (n : Size) -> T

Γ |- M : (n : Size) -> T  Γ |- N : Size
---------------------------------------
Γ |- M N : T[n := N]

//

Γ |- A : Type a  Γ, x : A |- B : Type b
---------------------------------------
Γ |- (x : A) -> B : Type (1 + b)

Γ |- A : Type a  Γ, x : A |- M : B
----------------------------------
Γ |- (x : A) => M : (x : A) -> B

Γ |- A : Type a  Γ |- M : (x : A) -> B  Γ |- N : A

--------------------------------------------------
Γ |- M N : B[x := N]


Nat s = (A : Type s) -> A -> (A -> A) -> A;


Fix = (x : Fix $) -> ();
fix = (x : Fix) => x [a] x;

f = (x : Nat n) : Nat (2 * n) => x + x;

fix 0 (fix 0)

Nat = (n : Size) -> (K : Type n) -> K -> (Nat -> )

(n : Size) => (A : Type n) => (x : A) => x;

Term [a] =
  | Var : [a] -> String -> Term [1 + a]
  | Abs : [a] -> String -> Term [a] -> Term [1 + a]
  | App : [a] -> [b] -> Term [a] -> Term [b] -> Term [1 + a + b];

Type : Type;
Data : Type;

⊥ = (A : *) -> A;
¬ φ === φ -> ⊥;S === S -> Type;

U : Kind = (X : Kind) -> (℘℘X -> X) -> ℘℘X;
τ (t : ℘℘U) : U = (X : Kind) => (f : ℘℘X -> X) => (p : ℘X) =>
  t ((x : U) => p (f (x X f)));
σ (s : U) : ℘℘U = s U τ;
 : U = τ ((p : ℘U) => (x : U) -> σ x p -> p x);S === S -> Type 0;

U : Type 2 = (X : Type 1) -> (℘℘X -> X) -> ℘℘X;
τ (t : ℘℘U) : U = (X : Type 1) => (f : ℘℘X -> X) => (p : ℘X) =>
  t ((x : U) => p (f (x X f)));

σ (s : U) : ℘℘U = s U τ;
 : U = τ ((p : ℘U) => (x : U) -> σ x p -> p x);


U : Type 0 = (X : Type 0) -> (℘℘X -> X) -> ℘℘X;



id : ()
  = s => A =>



Unit [0] = (A : Type) -> A -> A;
Unit [1 + a] = u @-> (P : Unit [b] -> Type) -> P (unit [a]) -> P (u [a]);


Id s : Type (2 + s) = (A : Type s) -> (x : A) -> A;
id s = A => x => x;

pair s : Type (2 + s + s) = (A : Type s) => x => (x, x)

Type : Type

Fix = Fix -> ();
fix = x => x x;

A => x => x

@u A x == x


Prop : Type;
Data : Type;
Type : Type;

Type : Type;

Term =
  | Type
  | (x : A) -> B
  | (x : A) => M
  | M N;

Eq<A>(x : A, y: A) = (P : A -> Type) -> P x -> P y;

Eq(Eq<Bool>(x, y), refl);


(l : List Int) -> Eq(bubble(l), quick(l));

bubble = quick

Prop :

(x : A, y : A) -> Eq(x, y);

a b -> a == b \/ a != b
(x : A : Prop) =>

f : () -> Unit;

f : (A : Prop) -> (x : A) -> x ==


Prop // single constructor
Set // equality is a mere proposition
Type

Prop : Type 0
Set : Type 0

Set : Type 0
Type 0 : Type 1
Type 0 == Type 0

(mem : Memory) =>

Int64(mem : Memory) = {
  addr : Pointer;
  is_valid : addr + 8 < length(mem);
};

Γ, x : @self(x). T |- Type
--------------------------
Γ |- @self(x). T : Type

Unit @=> u @-> (P : Unit -> Type) -> P (u @=> P => x => x) -> P u

!Unit = u @-> (P : @Unit I -> Type) -> P (I (u @=> P => x => x)) -> P (I u);
Unit = Unit @=> (I : I @-> !Unit -> @Unit I) => !Unit;


Unit : Type;
unit : Unit;

Unit = (u : Unit) @-> (P : Unit -> Type) -> P unit -> P u;
unit = P => x => x;

Bool : Type;
true : Bool;
false : Bool;

Bool = (b : Bool) @-> (P : Bool -> Type) -> P true -> P false -> P b;
true = P => x => y => x;
false = P => x => y => y;

Γ |- M : @self(x : A). B  Γ |- A ≂ @self(x : A). B
--------------------------------------------------
Γ |- M : B[x := M]


Inductive N2: Type :=
  | O : N2
  | S : N2 -> N2
  | mod2 : S (S O) = O.

N2 : Type;
zero : N2;
succ : (pred : N2) -> N2;
mod2 : succ (succ zero) == zero;

N2 = n @-> (P : N2 -> Type) -> P zero ->
  ((pred : N2) -> P (succ pred)) -> P n;
zero = P => z => s => z;
succ pred = P => z => s => pred (pred => P (succ pred)) (s z) z;
mod2 = refl;



Squash : (A : Type) -> Type;
box : (A : Type) (x : A) -> Squash A;

Squash = s @-> (P : Squash A -> Type) -> ((x : A) -> P (box A x)) -> P s;


succ : (pred : Nat) -> Type;


Type -> Type l


Term =
  | Type
  | x
  | (x [a] : A) -[b]> B
  | (x : A) => M
  | M N;

(x : A) -[s]> B

(A ['a]: Type) -[1]> (x ['x] : A) -['x]> A;
(A ['a]: Type) -[1]> (x ['k] : A) -> (y ['k] : A) -['k]> A;

(A ['a]: Type) => (x ['x] : A) => x

Nat = (A : Type) -> A -> (Nat -> A) -> A;

mu : (Type -> Type) -> Type;
mu = x => x x;S === S -> Type;

U : Type = (X : Type) -> (((X -> Type) -> Type) -> X) -> (X -> Type) -> Type;

Mu G = (X : Type) -> (G X -> X) -> X;S === S -> Type;


--------------

Id : Type 0 = |A : Type 0| -> (x : A) -> A;

Nat = (A : Type) -> A -> |A -> A| -> A;

U : Type 2 = (X : Type 1) -> (℘℘X -> X) -> ℘℘X;
τ (t : ℘℘U) : U = (X : Type 1) => (f : ℘℘X -> X) => (p : ℘X) =>
  t ((x : U) => p (f (x X f))); // fails as x X is invalid

σ (s : U) : ℘℘U = s U τ;
 : U = τ ((p : ℘U) => (x : U) -> σ x p -> p x);

Nat (Self : Type) = (A : Type) -> A -> (Self -> A) -> A;
Nat : Type = (X: Type) -> (℘℘X -> X);
unfold : Nat -> (A : Type) -> A -> (Nat -> A) -> A =

(A : Type) -> A -> ( -> A) -> A


Fix : Type;
fold : (Fix -> ()) -> Fix;
unfold : Fix -> (Fix -> ());

fold = (x : Fix -> ()) : Fix =>
  // introduce abstraction
  _;
unfold = (x : Fix) : (Fix -> ()) =>
  // eliminate abstraction
  _;

(A : Type) ->

// Type 0 implies in statically known size
((A : Type 0) -> A -> A) : Type 1;



Bool : Type 1 = ∀(l : Level).(A : Type l). A -> A - A;

U : Type 1 = (X : Type 0) ->
  (((X -> Type 0) -> Type 0) -> X) -> (X -> Type 0) -> Type 0;
τ (t : (U -> Type 0) -> Type 0) : U = (X : Type 0) => (f : ℘℘X -> X) => (p : ℘X) =>
  t ((x : U) => p (f (x X f)));

σ (s : U) : ℘℘U = s U τ;
 : U = τ ((p : ℘U) => (x : U) -> σ x p -> p x);

Sigma (l : Level) (A : Type l) (B : A -> Type l) : Type (1 + l) =
  s @-> (P : Sigma l A B -> Type l) ->
    (k : (x : A) -> (y : B a) -> P (s @=> P => k => k x y)) -> P s;

Sigma (l : Level) (A : Type l) (B : A -> Type l) : Type (1 + l) =
  s @-> (P : Sigma l A B -> Type l) ->
    (k : (x : A) -> (y : B x) -> P (s @=> P => k => k x y)) -> P s;

Sigma (l : Level) (B : Level -> Type l) : Type (1 + l) =
  s @-> (P : Sigma l B -> Type l) ->
    (k : (x : Level) -> (y : B x) -> P (s @=> P => k => k x y)) -> P s;
fst l B pair = @pair (_ )
(A : Type l)

Halting Problem

double = x => x + x;
does_a_for = n => {
  for (let i = n; i > 0; i--) {

  }
};
const loop = () => {
  while (true) {}
};
const loop = () => loop();
const map = (f, l) => {
  if (l.length == 0) {
    return [];
  }
  const [el, ...tl] = l;
  return [f(el), ...map(f, tl)];
};

true = (x => y => x);
false = (x => y => y);

one = z => s => s(z);
two = z => s => s(s(z));


pair x y = k => k x y;
(x => pair x x)
(x => x(x)) (x => x(x))


Array = {
  create : <A>(initial : A, len : Int, len_is_nat : length >= 0) -> Array<A>
} = _;

Array.create(0, -5, loop());


f : (x : number) -> (y : number) -> number
  = x            => y            => x + 1;

(x => x x) (x => x x)


Array = {
  create : <A>(initial : A, len : Int, len_is_nat : length >= 0) -> Array<A>
} = _;

incr : (x : Int) -> Int = _;
incr : (x : Int) ->? Int = _;
Array.create(0, -5, loop());
{
  "key": {
    "key": {
      "key": {
        "key": {
          "key": {
            "key": {}
          }
        }
      }
    }
  }
}

Large Elimination

Type : Type;

Dynamic

Bool = (A : Type) -> A -> A -> A;S === S -> Type;
U : Type = (X : Type) -> (℘℘X -> X) -> ℘℘X;
τ (t : ℘℘U) : U = (X : Type) => (f : ℘℘X -> X) => (p : ℘X) =>
  t ((x : U) => p (f (x X f)));
σ (s : U) : ℘℘U = s U τ;: U = τ ((p : ℘U) => (x : U) -> σ x p -> p x);

Nat [a] @=> (A : Type) -> A -> ((b < a) -> Nat [b] -> A) -> A;

(Unit [U_a]) @=> () -> (u : Unit [b]) @->
  (P : [b > a] -> Unit [c] -> Type) ->
    P [U_a] unit -> P [u_a] u;

(unit [u_a]) @=> (P : [a] -> ([a = 1 + b] -> Unit [b]) -> Type)

Unit = u @-> (P : Unit -> Type) -> P unit -> P u;


Bool : Type 1 = (A : Type 0) -> A -> A -> A;

Id = (A : Type _) -> A -> A;
id = (A : Type _) => (x : A) => x;
id Id id


P => u => p_unit : P u =>
  u
  | unit => p_unit;

(pred : _) => (x : pred (_ => Type) Int String) =>
  ()
id

Nat [a] = (A : Type) -> A -> ([b < a] -> Nat [b] -> A) -> A;

Unit [0] = (u : Unit []) @-> (P : Unit [] -> Type) -> P unit -> P u;
Unit [1 + a] = (u : Unit [a]) @-> (P : Unit [a] -> Type) -> P unit -> P u;

Unit [a] =
  (u [b < a] : Unit [b]) @-> (P : Unit [b] -> Type) -> P unit -> P u;

T_False : [a] -> Type;
T_False [a] =
  (False [b]) @->
  (f : (f [b]) @-> @False f) -> Type;

False : [b < a] -> T[a := b]


[k] -> (False [a < k]) @-> (f : (f [b = 1 + a]) @-> @False [b] f) -> Type;


Unit : [k] -> (Unit [a < k]) @-> Type;
Unit = [k] => (Unit [a < k]) @=> (u [b < a]) ->
  (P : Unit [b] -> Type) -> P unit -> P u;


[k] => (Nat [a < k]) @=> (n [b < a]) -> (P : Nat [b] -> Type) ->
  P zero -> ((pred : Nat [b]) -> P (succ pred)) -> P n;

[k] => (Nat [a < k]) @=> (n [b < a]) -> (P : Nat [b] -> Type) ->
  P zero -> ([c < a] -> (pred : Nat [c]) -> P (succ pred)) -> P n;


Term =
  | Type
  | (x : A) -> B
  | (x : A) => M
  | M N;

// naive
-----------------
Γ |- Size : USize

-------------
Γ |- 0 : Size

Γ |- a : Size
-----------------
Γ |- 1 + a : Size

// TODO: maybe this allows for some interesting elimination
Γ |- a : Size
--------------------
Γ |- Type a : Type a

Γ |- A : Type a  Γ, x : A |- B : Type b
---------------------------------------
Γ |- (x : A) -> B : Type (1 + a + b) // abstraction overhead

Γ, x : Size |- B : Type b
-------------------------------------------
Γ |- (x : Size) -> B : Type (1 + b[x := 0])

// fancy
-----------------
Γ |- Size : USize

-------------
Γ |- 0 : Size

Γ |- a : Size
-----------------
Γ |- 1 + a : Size

// TODO: all inhabitants besides of the universe itself are abstractions
Γ |- a : Size
--------------------------
Γ |- Type a : Type (1 + a) // abstraction overhead

Γ |- A : Type a  Γ, x : A |- B : Type b
---------------------------------------
Γ |- (x : A) -> B : Type (a + b)

Γ, x : Size |- B : Type b
---------------------------------------
Γ |- (x : Size) -> B : Type (b[x := 0])


(A : Type 0) -> (x : A) -> A : Type 1
(A : Type 1) -> (x : A) -> A : Type 4

((s : Size) -> (A : Type s) -> (x : A) -> A) : Type 1

(K : Type 0) -> (k : (A : Type 0) -> K) -> K : Type 1
(A : Type 0) -> (B : Type 0) -> A : Type 1

(s : Size) -> (K : Type s) -> (k : (A : Type s) -> K) -> K : Type 2


(s : Size) -> (A : Type s) -> (B : Type s) -> A : Type 1

Type (1 + l) == ((s : Size) -> Type (l + s))

(A : Type)

(x : Size) -> (A : Type x) -> A

(A : Type 0) -> (B : Type 0) -> A : Type 1
(s : Size) -> (U : Univ s) -> (A : U) -> (B : U) -> A : Type 1

// measuring how many sizes are unknown
Γ |- a : Size
--------------------
Γ |- Type a : Type a

(A : Type 0) ->

// Tarski
-----------------
Γ |- Size : USize

-------------
Γ |- 0 : Size

Γ |- a : Size
-----------------
Γ |- 1 + a : Size

Γ |- a : Size
--------------------------
Γ |- Univ a : Univ (1 + a) // universe overhead

Γ |- a : Size
--------------------
Γ |- Type a : Univ a

Γ |- A : K a  Γ, x : A |- B : K b
------------------------------------
Γ |- (x : A) -> B : Type (1 + a + b) // abstraction overhead

Γ, x : Size |- B : Type b
------------------------------------------- // compact
Γ |- (x : Size) -> B : Type (1 + b[x := 0]) // abstraction overhead

// (A : Type 0) -> (x : A) -> A : Type 1
(s : Size) -> ()
// (A : Type 0) -> (B : Type 0) -> A : Type 1
(s : Size) -> (U : Univ s) -> (A : U) -> (B : U) -> A : Type 1


// naive
-----------------
Γ |- Size : USize

-------------
Γ |- 0 : Size

Γ |- a : Size
-----------------
Γ |- 1 + a : Size

// TODO: maybe this allows for some interesting elimination
Γ |- a : Size
--------------------
Γ |- Type a : Type a

Γ |- A : Type a  Γ, x : A |- B : Type b
---------------------------------------
Γ |- (x : A) -> B : Type (1 + a + b) // abstraction overhead

Γ, a : Size |- T : Type b
---------------------------------------------
Γ |- (a : Size, x : T) : Type (1 + b[a := 0]) // indirection overhead


// (A : Type 0) -> A : Type 1
(s : Size, T : Type s) : Type 1
(s = 2, T = (A : Type 0) -> (B : Type 0) -> A) : Type 1

(s = 5, T = (A : Type 1) -> (B : Type 1) -> A) : Type 1


// naive
-----------------
Γ |- Size : USize

-------------
Γ |- ω : Size

Γ |- a : Size
------------------
Γ |- lift a : Size

Γ |- a : Size  Γ |- b : Size
----------------------------
Γ |- max a b : Size

Γ |- a : Size
---------------------------
Γ |- Type a : Type (lift a)

Γ |- A : Type (b < a)  Γ, x : A |- B : Type (c < a)
---------------------------------------------------
Γ |- (x : A) -> B : Type (a

Γ, [a] |- T : Type b
----------------------
Γ |- [a] -> T : Type ω

[x] -> [y < x] -> (A : Type 1) -> A

[a] =>

(x : Int) => x + 2 : (x : Int) -> Int

Id : Type 2 = (A : Type 1) -> A -> A;
Nat = (A : Type 0) -> A -> (Nat -> A) -> A;



-----------------
Γ |- Size : USize

Γ |- a : Size
------------------
Γ |- lift a : Size

Γ |- a : Size  Γ |- b : Size
----------------------------
Γ |- max a b : Size

Γ, a : Size |- b : Size  Γ, x : A |- B : Type
---------------------------------------------
Γ |- (x [a] : A) -[b]> B : Type

Γ, a : Size |- b : Size  Γ, x : A |- B : Type
---------------------------------------------
Γ |- (x : A) -[b]> B : Type

Γ |- M : (x : A % ) -[b]> B  Γ |- N : A
----------------------------------------
Γ |- M N : B[x := N] | n

Γ |- A : Type a  Γ, x : A |- B : Type b
---------------------------------------
Γ |- (x : A) -> B : Type (max a b)

Γ |- n : Grade  Γ, x : A |- B : Type b
--------------------------------------
Γ |- (x : A $ n) -> B : Type b

Fix = (x : Fix % 2) -> ();
fix = (x : Fix % 2) => x

Nat = n @-> (l : Level) -> (A : Type l $ 0) -> (zero : A $ 1) -> (succ : (acc : A $ 1) -> A $ l) -> A;

Id : Type = (A : Type) -> (x : A) -> A;
id : Id = (A : Type) => (x : A) => x;
id Id id

Nat : Type = (A : Type) -> A -> (A -> A) -> A;



Id : Type = (A : Type) -> (x : A % 2) -> A;

(fix) => fix fix;

Data = W @-> (T : Type, clone : (x : T) -> (l : W, r : W));

Unit : Type;
unit : Unit;
clone : (u : Unit) -> (l : Unit, r : Unit);

Unit = (A : Type) -> A -> A;
unit = A => x => x;
clone = u => u _ (unit, unit);


Unit [a] : Type;
unit [a] : Unit [1 + a];

Unit [a] = (u : (A : Type) -> A -> A, clone : [b < a] -> (l : Unit [b], r : Unit [b]));
unit [a] = (A => x => x, [b < a] => (unit [b], unit [b]));




Type l : Type (lift l);
(x : A : Type a) -> (B : Type b) : Type (max a b);

Bool : Type 0 = (A : Type ω $ 0) -> A -> A -> A;


Bool : Type 1 = (A : Type 0) -> A -> A -> A;
Bool : Type 1 = (l : Level) -> (A : Type l) -> A -> A -> A;

Bool : Type 0 = (A : Type ω) -> A -> A -> A;

Bool : Type 0 = b @-> (P : Bool -> Type ω $ 0) -> P true -> P false -> P b;

Restrictions

Usage tracking, grading prevents calling itself because eliminating a function requires one copy, plus the required copies from the the function itself, requiring n = n + 1 to work. Pro, can still call id with id.

Size tracking, predicativity prevents calling itself because a Type universe will never include itself, so a function can never take itself.

Why is impredicativity safe sometimes?

Teika

U = (A : Type, (A = A, A -> ()) -> ());
V = (A = U, A -> ());

V <: U;
(A = U, A -> ()) <: U
(A = U, A -> ()) <: (A : Type, (A = A, A -> ()) -> ())
(A = U, A -> ()) <: (A = U, (A = A, A -> ()) -> ())
U -> () <: (A = U, A -> ()) -> ()
(A = U, A -> ()) <: U



constraint = ['b < 'a];
constraint = ['b = 1 + 'a];

U : Type (1 + 'a) = (A : Type 'a, (A = A, A -> ()) -> ());
V = (A : Type (1 + 'a) = U, A -> ());

V <: (A : Type 'a, (A = A, A -> ()) -> ())
(A : Type (1 + 'a) = U, A -> ()) <: (A : Type 'b, (A = A, A -> ()) -> ())

1 + 'a = 'a

Id : Type 1 = (A : Type 0) -> (x : A) -> A;
id : Id = A => x => x;

Resource : Type;
Data : Type;
Property : Type;


U # 1 + 'u = (A # 1 : Type, (A # 1 = A, A -> ()) -> ());
V # 'v = (A = U, A -> ());

(A # 1 = U, A -> ()) # 'v <: U # 1 + 'u
(A # 1 = U, A -> ()) # 'v <: (A # 1 : Type, (A = A, A -> ()) -> ()) # 1 + 'u
(A # 1 = U, A -> ()) # 'v <: (A # 1 = U, (A = A, A -> ()) -> ()) # 1 + 'u
// clash, as 'u = 'u + 1


U = (A : Type, (A = A, A -> ()) -> ());
V = (A = U, A -> ());

V <: U;
(A = U, A -> ()) <: U


erase : (A : Type, x : P A) -> (A : Type, x : P A)


Univ : Univ;
Type : Univ;
Data : Univ;
Prop : Univ;

(b : Bool : Type) -> (() -> DNat) $ 1
(b : Bool) => (() => b DNat 0 1)

Memory : {
  type(mem : Memory, ptr : Pointer) : Type;
  get(mem : Memory, ptr : Pointer) : type(mem, ptr);
  set<A>(mem : Memory, ptr : Pointer, value : A) : Memory;
};
Rc<mem, A> = {
  ptr : Pointer;
  valid : Memory.length(mem) < ptr;
  witness : Memory.type(mem, ptr) == A;
};

℘S == S -> Type;

U : Type = (X : Type) ->
  (((X -> Type) -> Type) -> X) -> ((X -> Type) -> Type) -> X;
τ (t : ℘℘U) : U = (X : Type) => |f : ℘℘X -> X| => (p : ℘X) =>
  t ((x : U) => p (f (x X f)));
σ (s : U) : ℘℘U = s U τ;: U = τ ((p : ℘U) => (x : U) -> [σ x p ==> p x]);

U : Type = (X : Type) -> (℘℘X -> X) -> ℘℘X;: U = (X : Type) => |f : ℘℘X -> X| => (p : ℘X) =>
  ((p : ℘U) => (x : U) -> [σ x p ==> p x]) ((x : U) => p (f (x X f)));: U = (X : Type) => (f : ℘℘X -> X) => (p : ℘X) =>
  (x : U) -> [x U ((x : U) => p (f (x X f))) ==> p (f (x X f))] ;

(X : Type) -> ((G X) -> X) -> X;
(X : Type) -> (((R : Type) -> R -> (X -> R) -> R) -> X) -> X;

Id : Type 0 = (A : Type 0 $ 1) -> (x : A) -> A;

Nat = (A : Type)


(l : Level, x : Type (1 + l))


type M = Int -> Int;

M = Int -> Int;

Id = (A : Type) -> (x : A) -> A;
Id = ∀A. AA;


Id = <A>(x : A) -> A;

T = <A, B>(x : A, y : B) -> A;
U = <A, B>(x : A, y : B) -> B;


Eq A x y = (P : A -> Type) -> P x -> P y;
refl A x : Eq A x x = P => p => p;

(eq : A x x) -> Eq _ eq (refl A x)

Eq A x y = (P : A -> Type) -> P x -> P y;
refl A x : Eq A x x = P => p => p;

id = <A>(x : A) => x;


Unit = <A>(x : A) -> A;
Bool = <A, B>(x : A, y : A) -> A;


Type 0 : Type 1;
Type l : Type (1 + l);
Type: Type;

((A : Type) -> (x : A) -> A) : TypeT = <A, B>(x : A, y : B) -> A;
U = <A, B>(x : A, y : B) -> B;

NatA = | Zero | Succ (pred : NatA);
NatB = <A>(zero : A, succ : (pred : NatB) -> A) -> A;

NatA = <A>(zero : A, succ : (acc : A) -> A) -> A;
NatB = <A>(succ : (acc : A) -> A, zero : A) -> A;

T = <A, B>(x : A, y : B) -> A;
U = <A, B>(x : A, y : B) -> B;

Type 0 : Type 1;
<A : Type 0>(x : A) -> A;

Inductive circle : Type :=
  | base : circle
  | loop : base == base.

(Type 0 : Type 1)

(Set : Type 0);
(Type l : Type (1 + l));

* :: Δ


(A : *) -> A : *
(A : *) -> (B :) -> A : *
(A :) -> (B : Δ) -> A : Δ

Type 0 : Type 1
Type 1 :
(B :) -> (A : *) -> A : *

Type l : Type (1 + l);
Data l : Type (1 + l);
Prop l : Type (1 + l);

Type : Type;
Data : Type;
Prop : Type;

Type : Type;
Prop : Type;

PNever : (A : Prop) -> A;
TNever : (A : Type) -> A;

never_magic : PNever -> TNever = _;

PUnit = (A : Prop) -> (x : A) -> A;
TUnit = (A : Type) -> (x : A) -> A;

unit_magic : PUnit -> TUnit = _;

T = <A>(x : A) -> <B>(y : B) -> A;
U = <A, B>(x : A) -> (y : B) -> A;

id = (A : Prop) => (x : A) => x;

id ((A : Type) -> A)

f : (A : Type) -> (B : Prop) -> B : Prop;


(l = 2, A = Type (l + l)) : (l : Level, A : Type (1 + l + l)) : Type 2
(l = 2, A = Type l) : (l : Level, A : Type (1 + l)) : Type 2

Type l : Type (1 + l);
Data l : Type (1 + l);
Prop l : Type (1 + l);

{ A : Data l: ; x : A }

Bool : Data 2;
true : Bool;
false : Bool;

Bool = b @-> (
  d : (P : Bool -> Data 1) -> P true -> P false -> P b &
  t : (P : Bool -> Type 1) -> P true -> P false -> P b
);
true : Bool = (P => x => y => x & P => x => y => x);
false : Bool = (P => x => y => y & P => x => y => y);


Sigma A B = s @-> (P : Sigma A B -> Data 0) ->
  (k : (x : A) -> (y : B x) -> P (exist A B x y)) -> P s;

U : Data 2 = (X : Data 1) ->
  (((X -> Data 0) -> Data 0) -> X) -> ((X -> Data 0) -> Data 0) -> X;
τ (t : ℘℘U) : U = (X : Type) => |f : ℘℘X -> X| => (p : ℘X) =>
  t ((x : U) => p (f (x X f)));
σ (s : U) : ℘℘U = s U τ;: U = τ ((p : ℘U) => (x : U) -> [σ x p ==> p x]);

Data : Type;
Prop : Type;


id : (A : Data) -> (x :A) -> ⇑A = _;

Unit = (A : Data) -> (x : A) -> A;

(u : Unit) => (A : Type) => (x : A) => u A x;

Unit = u @-> (P : Unit -> Data) ->
(A : Data) -> (x : A) ->

Data l : Type (1 + l);
Type l : Type (1 + l);


Id : Data = (A : Data : Type) -> (x : A : Data) -> A;
Id : Type = ⇑Id;

id = (A : Data) => (x : A) => x;

Type l : Type (1 + l); // no elimination to Data
Data l : Type (1 + l); // no universes in Data

Unit : Data 1;
unit : Unit;

Unit = u @-> (
  d : (P : Unit -> Data 0) -> P unit -> P u,
  T : (P : Unit -> Type 0) -> P unit -> P u
);
unit = (
  d = P => x => x,
  T = P => x => x,
);



S = {
  A : Data;
  x : A;
};
id = (A : Data) => (x : A) => x;

x = id (@squash Type)
Eq A B = (P : Data -> Data) -> P A -> P B;(A : Data) => (x : A) => x
(A :Data) => (x : ⇑~A) => x
lifted_id : (A : Type) -> (x : A) -> A = ⇑id;
// rules
// Those rules they require mutually recursive blocks to be useful
Γ, x : A |- B : Type
---------------------------
Γ |- @self(x : A). B : Type

Γ, x : A |- M : B[x := @fix(x : A). M]  Γ |- A ≂ @self(x : A). B
----------------------------------------------------------------
Γ |- @fix(x : A). M : @self(x : A). B

Γ |- M : @self(x : A). B  Γ |- A ≂ @self(x : A). B
--------------------------------------------------
Γ |- @unroll M : B[x := M]



Γ, x : A |- B : Type  Γ |- A ≂ @self(x : A). B
----------------------------------------------
Γ |- @self(x : A). B : Type

/*
3 general steps

Describe the type indexed by the constructors of the type
Make the type family itself
Close the family on the constructors

The following code assumes implicit unroll
*/

// shape of family
T_P_Unit : Type;
T_p_unit : (P_Unit : T_P_Unit) -> Type;

T_P_Unit = @self(P_Unit : T_P_Unit). (p_unit : T_p_unit P_Unit) -> Type;
T_p_unit P_Unit = @self(p_unit : T_p_unit P_Unit). P_Unit p_unit;

// proto Unit
P_Unit : T_Unit;
p_unit : T_p_unit P_unit;

P_Unit p_unit = @self(u : P_Unit p_unit).
  (P : P_Unit p_unit -> Type) -> P p_unit -> P u;
p_unit = @fix(p_unit). P => (x : P p_unit) => x;

// closing
Unit = P_Unit p_unit;
unit : Unit = p_unit;

T_False : Type;
T_f : (False : T_False) -> Type;

= @self(f : T_False)

Unit : Type;
unit : Unit;

Unit = @self(u : Unit). (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;

data Z4 : Set where
  zero : Z4
  suc : Z4 -> Z4
  mod : suc (suc (suc (suc zero))) ≡ zero


// Those rules they require mutually recursive blocks to be useful
Γ, x : A |- B : Type
---------------------------
Γ |- @self(x : A). B : Type

Γ, x : A |- M : B[x := @fix(x : A). M]  Γ |- A ≂ @self(x : A). B
----------------------------------------------------------------
Γ |- @fix(x : A). M : @self(x : A). B

Γ |- M : @self(x : A). B  Γ |- A ≂ @self(x : A). B
--------------------------------------------------
Γ |- @unroll M : B[x := M]


False @-> (f : f @-> @False f) -> Type;

// induction-induction
A : Type;
B : (K : A) -> Type;

// my-stuff
T_False : Type;
T_f : (False : T_False) -> Type;

T_False = @self(False : T_False). (f : T_f False) -> Type;
T_f False = @self(f : T_f False). @False f;



@self(False : T_False). (f : @self(). ) -> Type;

@self(A : Type, T_f : _).
  (False : @self(False :)) => @False f

T_f : @self(A, T_f : ). (False : @self(False). (f : T_f) -> Type) -> Type;
T_f = @fix(T_f : _). False => @self(f : @T_f False). @False f;

@exist(T_False : Type).
  @self(False :
    @self(False : T_False). (f : @exist(T_f : Type). T_f) T_False).
    (f : @exist(T_f : Type). @self(f : T_f). @False f) -> Type;
@both(
  T_False : Type = @self(False : T_False). (f : T_f False) -> Type,
  T_f : (False : T_False) -> Type = False => @self(f : T_f False). @False f
)

Γ |- T : @both(x : A = M, y : B = N)
------------------------------------
Γ |- @fst T : M[x := M | y := N]

Γ |- T : @both(x : A = M, y : B = N)
------------------------------------
Γ |- @snd T : N[x := M | y := N]



Γ, x : Type |- B : Type  Γ, y : B |- M : Type  Γ |- N[x := M] : B
-----------------------------------------------------------------
Γ |- @ind(x = M, y : B = N) -> Type


Γ, A : Type, x : A |- B : Type
-------------------------------
Γ |- @self(A, x : B). T : Type

@self(_, T_False : Type).
  @self(False : T_False). (f : @self(T_f, f : T_f). ) -> Type;

@self(A, T_f : A -> Type).
  False => @self(B, f : T_f False). _ => @False f

@self(False, f). False =>

@self(False : T_False). (f : @self(f : T_f). @False f) -> Type;



-----------------
Γ |- Self : USelf

Γ, x : @self(x). T |- T : Type
-------------------------------
Γ |- @self(x). T : Type

Γ |- M : @self(A, x). T
--------------------------
Γ |- @unroll M : T[x := M]

Γ, A : Type, x : A |- T : Type
-------------------------------------
Γ |- @self(A, x). (y : B) => T : A -> Type

False @-> (f : f @-> @False f) -> Type;

@self(T_False, False : @self(_, False : T_False). (f : )).
  (f : @self(T_f, f : T_f). @False f) -> Type;

Γ, A : Type, x : A |- T : Type
------------------------------
Γ |- @self(A, x). T : Type

Unit = @self(Unit, u). (unit : Unit) -> (P : Unit -> Type) -> P unit -> P u;

False = False @-> (f : f @-> @False f) -> Type;

A : Type;
B : (x : A) -> Type;

A = @self(x : A). (f : B x) -> Type;
B False = @self(f : B x). @x f;

A : Type;
B : (x : A) -> Type;

A = _;
B x = _;

Γ, x : A |- T : Type
---------------------------
Γ |- @self(x : A). T : Type

Nat = | Zero | Succ (pred : Nat);

Unit : Type;
unit : Unit;

Unit = @self(u : Unit). (P : Unit -> Type) -> P

Γ, x : A |- T : Type
------------------------------
Γ |- @self(A, x). T : Type

Γ, A : Type, x : A |- T : Type
------------------------------
Γ |- @self(A, x). T : Type



Type : Type = _;
Data : Type = _;

Mu G = (X : Type) -> (G X -> X) -> X;
Nat_G INat = (K : Type) -> X -> (INat -> Type) -> K;

Nat X = (K : Type) -> (A : Type) -> (k : A -> K) -> (z : A) ->
  (s : (k : A -> K) -> (z : A) -> (p : X) -> K) -> K;
Nat_n = (X : Type) -> (Nat X -> X) -> X;

Show : Data = {

};

T_False : Type;
T_f : (False : T_False) -> Type;

T_False = (False : T_False) @-> (f : T_f False) -> Type;

μ T. (eq : μ E. (T == μ T. (eq : E) -> _)) -> _;
@self(u : Unit).


(X : Type) -> (G X -> X) -> X;

Γ, x : A |- T : Type
---------------------------
Γ |- @self(x : A). T : Type

Γ, x |- , x : A |- T : Type
-------------------------------------
Γ |- @fix(x : A). M : @self(x : A). T


T_P_Unit : Type;
T_p_unit : (P_Unit : T_P_Unit) -> Type;

T_P_Unit = @self(P_Unit : T_P_Unit). (p_unit : T_p_unit P_Unit) -> Type;
T_p_unit P_Unit = @self(p_unit : T_p_unit P_Unit). P_Unit p_unit;

P_Unit : T_Unit;
p_unit : T_p_unit P_unit;

P_Unit p_unit = @self(u : P_Unit p_unit).
  (P : P_Unit p_unit -> Type) -> P p_unit -> P u;
p_unit = @fix(p_unit). P => (x : P p_unit) => x;



Γ, x : A, y : B |- M : A  Γ, x == M, y : B |- N : B
---------------------------------------------------
Γ |- { x : A, y : B, x = M, y = N } : Type


Γ, x : A, y : B |- M : A  Γ, y : B[x := M] |- N : B[x := M]
------------------------------------------------------------
Γ |- (x : A, y : B, x = M, n = N) : (x : A, y : B)

Γ |- M : (x : A, y : B)
------------------------------------------------------------
Γ |- M.x : A[x := fst M][y := snd M]

Γ |- M : (x : A = , y : B)
------------------------------------------------------------
Γ |- (x, y) = M; N : T

Γ, x : A, y : B |- M : A  Γ, y : B[x := M] |- N : B[x := M]
------------------------------------------------------------
Γ |- (x : A; T) : (x : A, y : B)

Γ, x : A, y : B | T) : (x : A, y : B)





Γ, x : A |- M : A  Γ, x == M |- N : B
-------------------------------------
Γ |- (x : A; x = M; x) : B[x := M]

Γ, x : A |- M : A  Γ, x == A |- N : Type
----------------------------------------
Γ |- (x : A; x = M; N) : Type

Γ, x : A |- M : A  Γ, x == M |- N : B
------------------------------------------
Γ |- (x : A; x = M; N) : (x : A; x = M; B)

T_Unit : Type;
Unit : T_Unit;

T_Unit = (unit : Unit) -> Type;
Unit = unit =>


Unit : Type;
unit : Unit;

Unit = (u : Unit) @-> (P : Unit -> Type) -> P unit -> P u;
unit = (u : Unit) @=> P => x => x;



False : Type;
False = (f : False; f : (P : False -> Type) -> P f);

Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P u) => x;

T_Unit : Type;
T_unit : (Unit : T_Unit) -> Type;

T_Unit = (Unit : T_Unit) & (unit : T_unit Unit) -> Type;
T_unit = (unit : T_unit Unit) & Unit

Γ |- M : B  Γ, x == A |- M : B  Γ |- A(x : A) & B
--------------------------------------------
Γ |- M : (x : A) & B

(u : Unit & (P : Unit -> Type) -> P unit -> P u)

Unit : T_Unit;
Unit = (
  @Unit : (unit : T_unit Unit) -> Type;
  @Unit (unit : T_unit Unit)  =
)

M = (
  Unit : Type;
  unit : Unit;

  Unit = @self(u : Unit). (P : Unit -> Type) -> P unit -> P u;
  unit = @fix(u : Unit). P => x => x;
)

M.Unit === @self(u : M.Unit). (P : M.Unit -> Type) -> P unit -> P u
T_Unit = ()
Unit : Type;
unit : Unit;


Unit = @self()

T_Unit : Type;
T_unit : (Unit : T_Unit) -> Type;

T_Unit = (Unit : T_Unit) & (unit : T_unit Unit) -> Type;
T_unit = (Unit : T_Unit) => (unit : T_unit Unit) & Unit;


Bool : Type;
true : Bool;
false : Bool;

Bool = @self(b). (P : Bool -> Type) -> P true -> P false -> P b;
true = P => x => y => x;
false = P => x => y => y;


Bool : Type;
true : Bool;
false : Bool;

Bool = @self(b : Bool). (P : Bool -> Type) -> P true -> P false -> P b;
true = P => x => y => x;
false = P => x => y => y;


Bool = (b : (P : Type) -> P -> P -> P) & (P : Bool -> Type) -> P true -> P false -> P b;
true = (P : ?) => x => y => x;

M : (x : A) & B;
N : (x : A) & B;

M.0 == N.0 -> M == N;


C_Bool : Type;
c_true : C_Bool;
c_false : C_Bool;

C_Bool = (A : Type) -> A -> A -> A;
c_true = A => x => y => x;
c_false = A => x => y => y;

I_Bool : (c_b : C_Bool) -> Prop;
i_true : I_Bool c_true;
i_false : I_Bool c_false;

I_Bool c_b = (P : C_Bool -> Prop) -> P c_true -> P c_false -> P c_b;
i_true = P => x => y => x;
i_false = P => x => y => y;

Bool : Type = (c_b : C_Bool, I_Bool c_b);
true : Bool = (c_b = c_true, i_true);
false : Bool = (c_b = c_false, i_false);

Bool : Type;
true : Bool;
false : Bool;

Bool = (b : (A : Type) -> A -> A -> A &
  (P : Bool -> Prop) -> P true -> P false -> P b);
true = (b = A => x => y => x,);
false = P => x => y => y;



expected : (P : Bool -> Type) -> P true -> P false -> P true
received : (P : Bool -> Type) -> P true -> P false -> P true

Type : Type;
Data : Type;
Prop : Type;

(x : Nat & x >= 5);
(x = 5 & le_refl)

(a : (x : Nat & x >= 5)) => (b : (x : Nat & x >= 5)) => (eq : fst a == fst b) =>
  a == b
(A : Prop) => (x : A) => (y : A) => (refl : x == y)

Unit : Type;
unit : Unit;

Unit = (P : Unit -> Type) -> P unit -> P unit;
unit = (P : Unit -> Type) => (x : P unit) => x;


t = (False : Type) => (f : A) => (False == (P : False -> Type) -> P f) =>
  (f )

False : Type;
False = <K>(k : <F>(f : F, F == (P : F -> Type) -> P f) -> K) -> K;

Unit : Type;
Unit = <K>(k : <U>(u : F, F == (P : F -> Type) -> P f) -> K) -> K;

Unit : Type;
Unit = <K>(k : <U>(u : F, F == (P : F -> Type) -> P f) -> K) -> K;



MUnit Unit unit u = (P : Unit -> Type) -> P unit -> P u;


t = (T : Type) =>
  (unit : A) => (A == T unit)
  (U : Type) => (u : U) => (U == (P : _ -> Type) -> P unit -> P u) =>

Bool : Set 1
true : Bool
false : Bool

Bool = ι(b : Bool).(P : Bool -> Set 0). P true → P false → P b
true = λ(P : Bool -> Type). λ(then : P true). λ(else : P false). then
false = λ(P : Bool -> Type). λ(then : P true). λ(else : P false). else



False : Type;
False = <K>(k : <F>(f : F, F == (P : F -> Type) -> P f -> ()) -> K) -> K;

T_dumb : Type;
dumb : T_dumb;

T_dumb = (P : T_dumb -> Type) -> P dumb -> ();
dumb = P => x => ();

false : False;
false = k => k(dumb, refl);


P_Unit : Type;
p_unit : P_Unit;

P_Unit = (P : P_Unit -> Type) -> P p_unit -> P p_unit;
p_unit = P => x => x;

WBool : Type;
WBool = <K>(k : <Bool>(true : Bool) -> (false : Bool) ->
  (ind : (b : Bool) -> (P : Bool -> Type) -> P true -> P false -> P b) ->
  (ind_true : ind true == P => x => y => x) ->
  (ind_false : ind false == P => x => y => y) ->
  (b : Bool) -> K
  K) -> K;

WBool : Type;
WBool = <K>(k :
  <Bool>(true : (A : Type) -> Bool A) ->
    (false : (A : Type) -> Bool A) ->
  <B>(b : Bool B) ->
    (ind : (P : Bool B -> Type) -> P (true B) -> P (false B) -> P b) ->
  K
  K) -> K;

MBool : _ -> Type;

Bool : _ -> Type;
true : _ -> Bool _;
false : _ -> Bool _;
ktrue : Bool (true true);
kfalse : Bool (false false);

Bool b = (P : Bool b -> Type) -> P (true b) -> P (false b) -> P b;
true b =
ktrue = (P : Bool ktrue -> Type) => (x : P ktrue) => (y : P kfalse) => x;
kfalse = (P : Bool ktrue -> Type) => (x : P ktrue) => (y : P kfalse) => y;
false b = (P : Bool b -> Type) => (x : P (true b)) => (y : P (false b)) => y;
T_true = Bool;
T_false = Bool;

Bool b = (P : Bool b -> Type) -> P true -> P false -> P b;





Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;



Bool : Type;
true : Bool;
false : Bool;
MBool : (b : Bool) -> Type;

MBool b = (P : Bool -> Type) -> P true -> P false -> P b;
Bool =

Bool b = (P : T_b -> Type) -> P (true b) -> P (false b) -> P b;


f =  <B>(b : Bool B) -> (ind : (P : Type -> Type) -> P T -> P F -> P B) ->

A : Type;
B : A -> Type;

Sigma : Type;
sigma : (x : A) -> (y : B x) -> Sigma A B;

s : Sigma A B;
Sigma = A => B => (P : Sigma A B -> Type) ->
  (k : (x : A) -> (y : B x) -> P (sigma A B x y)) -> P s;

sigma = A => B => x => y => P => k => k x y;

A : Type;
B : A -> Type;

f = (S : Type) => (s : S) =>
  ()
  (fst : (s : S) -> A) =>
  (snd : (s : S) -> B (fst s)) => _;

Sigma A B = s @-> (P : Sigma A B -> Type) ->
  ((x : A) -> (y : P x) -> P (sigma A B x y)) -> P s;

T : Type;

f (K => k => k x y)
  (s => )


f = <F>(f : F) => (F == (P : F -> Type) -> P f) =>


Bool : Type;
true : Bool;
false : Bool;

Bool = (b : Bool & (P : Bool -> Type) -> P true -> P false -> P b);

M :


expected : b Type True False
received : b.x Type True False

Γ, x : A |- M : B[x := @fix(x : A). M]  Γ |- A ≂ @self(x : A). B
----------------------------------------------------------------
Γ |- @fix(@(x : A)). M : @self(x : A). B

T == (P : Unit -> Type) -> P unit -> P unit
B == (P : Unit -> Type) -> P unit -> P unit


(F : Type) => (F == @self(x : F). (P : F -> Type) -> x) =>

B
---------------
M(x : A & B);


Γ, x : A |- M : B[x := M]  Γ |- A ≂ @self(x : A). B
---------------------------------------------------
Γ |- @fix(@unfold x : B). M : @self(x : A). B

Γ, x : A |- M : B[x := M]  Γ |- A ≂ @self(x : A). B
---------------------------------------------------
Γ |- @fix(@fold x : B). M : @self(x : A). B

Unit : Type;
unit : Unit;

Unit = @self(u : Unit). (P : Unit -> Type) -> (x : P unit) -> P u;
unit = @fix(@unfold u). (P : Unit -> Type) => (x : P (@fold u)) => x;


T_Unit : Type;
T_unit : (Unit : T_Unit) -> Type;

T_Unit = (Unit : T_Unit & (unit : T_unit Unit) -> Type);
T_unit = (unit : T_unit Unit & Unit unit);

Unit : T_Unit;

Unit unit = (u : Unit unit & (P : Unit unit -> Type) -> P unit -> P u);

PT_unit : Type;
unit : PT_unit;

unit : T_unit Unit;
unit = (P : Unit unit -> Type) => (x : P unit) => x;



Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : Unit -> Type) -> P unit -> P u;
unit = (P : Unit -> Type) => (x : P unit) => x;

// check
(unit : (P : Unit -> Type) -> P unit -> P unit) <: Unit

// rule



((M : A) :> T) == ((N : A) :> T)

M == N
(T_Unit : Type; T_Unit = (Unit : T_Unit))


Bool : Data 1;
true : Bool;
false : Bool;

Bool = (b : Bool & (P : Bool -> Data 0) -> P true -> P false -> P b);
true = (P : Bool -> Data 0) => (x : P true) => (y : P false) => x;
false = (P : Bool -> Data 0) => (x : P true) => (y : P false) => y;


// core
------------------------
Γ |- Type : Type

Γ, x : A |- B : Type
------------------------
Γ |- (x : A) & B : Type

Γ |- x : A |- B : Type
------------------------
Γ |- (x : A) -> M : Type

Γ, x : A |- M : B
--------------------------------
Γ |- (x : A) => M : (x : A) -> B

Γ |- M : (x : A) -> B  Γ |- N :> A
----------------------------------
Γ |- M N : B[x := N]

// coercion
Γ |- M : T
-----------
Γ |- M :> T

Γ |- M :> A  Γ |- M :> B[x := M]
--------------------------------
Γ |- M :> (x : A) & B

Γ |- M :> (x : A) & B
---------------------
Γ |- M :> A

Γ |- M :> (x : A) & B
---------------------
Γ |- M :> B[x := M]


// base
Γ |- MT
-----------
Γ |- MT

Γ |- MT
----------------
Γ |- (M : T)T

// universe
------------------------
Γ |- TypeType

// forall
Γ |- AType  Γ, x : A |- BType
-----------------------------------
Γ |- (x : A) -> MType

Γ, x : A |- MB
--------------------------------
Γ |- x => M(x : A) -> B

Γ |- M(x : A) -> B  Γ |- NA
----------------------------------
Γ |- M NB[x := N]

// intersection
Γ |- AType  Γ, x : A |- BType
-----------------------------------
Γ |- (x : A) & BType

Γ |- MA  Γ |- MB[x := M]
--------------------------------
Γ |- M(x : A) & B

Γ |- M(x : A) & B
---------------------
Γ |- MA

Γ |- M(x : A) & B
---------------------
Γ |- MB[x := M]


T_Unit : Type;
T_Unit = (Unit : T_Unit) &
  (unit : (T_unit : Type; (unit : T_unit) & T_Unit)) -> Type

// induction-induction
T_Unit : Type;
T_unit : (Unit : T_Unit) -> Type;

T_Unit = (Unit : T_Unit) & (unit : T_unit Unit) -> Type;
T_unit = Unit => (unit : T_unit Unit) & Unit unit;

// fixpoint
Unit : T_Unit;
Unit unit = (u : Unit unit) & (P : Unit unit -> Type) -> P unit -> P u;

// fixpoint
unit : T_unit Unit;
unit = @fix(unit : T_unit Unit). P => x => x;

Γ |- A : Type  Γ, x : A |- A : Type
---------------------------------------
Γ |- (x : A; y : B; x = M; y = N; K)(x : A) & B

Γ |- A(x : A) & B  Γ, y : A |- MB
---------------------------------------
Γ |- @fix(x). M(x : A) & B

False : Type;
False = (f : False) & (P : False -> Type) -> P f;

T_Unit : Type;
T_Unit = (Unit : T_Unit) & (A : Type) -> (unit : ) -> Type;

Unit : Type;
Unit = (u : Unit) & (P : Unit -> Type)

(u : Unit) & (P : Unit -> Type) ->

Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : Unit -> Type) -> P unit -> P u;
unit = @fix(unit). P => x  => y

Unit == @fix(Unit). (u : Unit) & (P : Unit -> Type) -> P unit -> P u;

[] |- (unit : (P : Unit -> Type) -> P unit -> P unit) :> Unit
[unit : (P : Unit -> Type) -> P unit -> P unit :> Unit] |-
  received : (P : Unit -> Type) -> P unit -> P unit
  expected : (u : Unit) & (P : Unit -> Type) -> P unit -> P u

  [unit : (P : Unit -> Type) -> P unit -> P unit :> Unit] |-
    received : (P : Unit -> Type) -> P unit -> P unit
    expected : (P : Unit -> Type) -> P unit -> P unit


  [] |- (unit : (P : Unit -> Type) -> P unit -> P unit) :>
    (u : Unit) & (P : Unit -> Type) -> P unit -> P u
P : A -> Type;
P (M : A & B) == P (N : A)
(M : A & B) == (N : A) : A

Γ |-


(x : Nat & x >= 5) => x + 1

f : () -> Nat;

x = 1;


f = () => f ();

Type 0 : Type 1
Type 1 : Type 2

id : (A : Type 0) -> (x : A) -> A
  = (A : Type 0                                                                                                                                                                                                                                                                                                     ) => (x : A) => x;

Show = {
  T : Type 0;

}


Unit : Type;
unit : Unit;

Unit = (u : Unit & (P : Unit -> Type) -> P unit -> P u);
unit = (P : Unit -> Type) => (x : P unit) => x


Γ, x : A, y : B |- M : A  Γ, x : A, y : B, x == M |- N : B
Γ, x : A, y : B, x == M, y == N |- K : T
----------------------------------------------------------------------
Γ |- (x : A; y : B; x = M; y = N; K) : (x : A; y : B; x = M; y = N; T)


Γ |- M : A  Γ, x == M |- K : T
------------------------------
Γ |- (x = M; K) : (x = M; T)



f : <A, B>(x : A, y : B) -> A;
g : <A, B>(x : A, y : B) -> B;


f : <A, B>(x : A, y : B) -> A;

Hot : Type;
Hot = T @-> (A : Type, eq : (B : Type) -> A =~= B -> A == B);

Set : Type;

Set = (A : Type, eq : (P : ) -> (x : A) -> -> P (eq == refl));

Unit : Type;
unit : Unit;
uip : (u : Unit) -> (eq : u == u) -> eq == refl;

SUnit : Type;
SUnit_eq : (s : SUnit) -> Type;
SUnit_refl : (s : SUnit) -> SUnit_eq s;

SUnit = s @-> (x : Unit, eq : SUnit_eq);
SUnit_eq s = e @-> (eq : s == s) ->
  (P : s == s -> SUnit_eq s -> Type) -> P refl SUnit_refl -> P s e;
SUnit_refl s =

Unit : Set;
Unit = (A = unit)

Prop : Type;
Prop = T @-> (
  A : Type,
  eq : (x : T) -> (y : T) -> (P : T -> Type) -> P x -> P y
);

Unit : Set;


Γ, x : @self(x). T |- T : Type
------------------------------
Γ |- @self(x). T : Type

Γ, x : @self(x). T |- M : T
---------------------------------
Γ |- @fix(x) : T. M : @self(x). T

Γ |- M ⇒ @self(x). T
--------------------
Γ |- MT[x := M]



T_Unit : Type = @self(Unit). _ -> _ -> _ -> Type;
T_unit : Type = _;

Unit : T_Unit = @fix(Unit). I0 => unit => I1 => (
  Unit = @unroll Unit I0 unit I1;
  I0 = @unroll I0 unit I1;
  unit = @unroll Unit I1;
  @self(u). (P : Unit -> T'ype) -> I0 P unit -> I0 P u
);
I0 = _;
unit : T_unit = @fix(unit). I1 =>
  @fix(u). (P : Unit -> Type) => (x : P unit) => I1 P x;
unit : @self(unit). @unroll Unit unit = @fix(unit).


T_Unit : Type;
T_unit : (Unit : T_Unit) -> Type;

T_Unit = @self(Unit : T_Unit). (unit : T_unit Unit) -> Type;
T_unit = Unit => @self(unit : T_unit Unit). @unroll Unit unit;

Unit : T_Unit = @fix(Unit). unit => @self(u : @unroll Unit unit).
  (P : @unroll Unit unit -> Type) -> (x : P unit) -> P u;
unit : @self(unit : T_unit Unit).
  @self(u : @unroll Unit unit).
  (P : @unroll Unit unit -> Type) -> (x : P (@unroll unit)) -> P u = @fix(unit).

M : @self(unit : T_unit Unit). @self(u : Unit unit).
  (P : Unit unit -> Type) -> (x : P unit) -> P u
@unroll M : @self(u : Unit M). (P : Unit M -> Type) -> (x : P M) -> P u
@unroll (@unroll M) : (P : Unit M -> Type) -> (x : P M) -> P (@unroll M)


T_Unit : Type;
T_unit : (Unit : T_Unit) -> Type;

T_Unit = (Unit : T_Unit) & (unit : T_unit Unit) -> Type;
T_unit = Unit => (unit : T_unit Unit) & Unit unit;

Unit : T_Unit = @fix(Unit). unit =>
  (u : Unit unit) & (P : Unit unit -> Type) -> (x : P unit) -> P u;

(unit : T_unit Unit) & (u : Unit unit) & (P : Unit unit -> Type) -> (x : P unit) -> P u ==
(unit : T_unit Unit) & (P : Unit unit -> Type) -> (x : P unit) -> P unit

(unit : T_unit Unit) & (u : Unit unit) & (P : Unit unit -> Type) -> (x : P unit) -> P u

unit : (unit : T_unit Unit) & Unit unit =
  @fix(unit). (P : Unit unit -> Type) -> (x : P unit) -> P u;
Unit : Type;
unit : Unit;

Unit = @self(u : Unit). (P : Unit -> Type) -> P unit -> P u;
unit = @fix(u : Unit). (P : Unit -> Type) => (x : P unit) => x;


M : @self(a). @self(b). (P : T -> Type) -> P (@unroll a) -> P b;


Γ, x : @self(x). T |- TType
------------------------------
Γ |- @self(x). TType

Γ, x : @self(x). T |- MT
-----------------------------
Γ |- @fix(x). M ⇐ @self(x). T

Γ |- M ⇒ ιx. T
------------------
Γ |- MT[x := M]


M { false = _; true = _; ...R; }

(M | true => _ | false => _)


(x => M) N
(x => f (x x)) (x => f (x x))

T_Unit : Type = @self(Unit). (unit : @self(unit). Unit unit) -> Type;
Unit : T_Unit = @fix(Unit). unit =>
  @self(u). (P : Unit -> Type) -> P unit -> P u;



// context
-----------
• : Context

Γ : Context  x ∉ Γ  Γ |- A : Type
--------------------------------- // term hypothesis
(Γ, x : A) : Context

Γ : Context  x ∉ Γ  Γ |- M : A
------------------------------ // unlocked equality
(Γ, x == M) : Context

Γ : Context  x ∉ Γ  Γ |- M : A
------------------------------ // locked equality
(Γ, [x == M]) : Context

Γ : Context
------------- // unlock all equalities
|Γ| : Context

Γ : Context  _ :> x ∉ Γ  Γ |- M : A  Γ |- x : Type
-------------------------------------------------- // coercion hypothesis
(Γ, M :> x) : Context

// equality
// TODO: type formation may depend on equality??
// TODO: prevent kind formation from depending on equality??

Γ | Δ |- A : Type  Γ | Δ |- MType  Γ |- MA
--------------------------------------
Γ | Δ |- MN : A

// rule
Γ : Context  Γ |- AType  Γ |- MA
-------------------------------------- // infer
Γ |- MA

Γ : Context  Γ |- AType  Γ |- MA
-------------------------------------- // check
Γ |- MA

Γ : Context  Γ |- AType  Γ |- MS  Γ |- M :> A
--------------------------------------------------- // coercion
Γ |- M :> A

// TODO: maybe both should check?
Γ : Context  Δ : Context  Γ |- AType  Γ |- MA  Γ |- NA
--------------------------------------------------------------- // equality
Γ | Δ |- MN : A

// infer
// TODO: bad notation, unlock on infer
|Γ| |- MA
------------
Γ |- MA

Γ |- MA
----------------
Γ |- (M : A)A

// check
Γ |- MS  Γ |- (M : S) :> T
-----------------------------
Γ |- MT

Γ, [x == A], M :> x |- MA
----------------------------
Γ, x == A |- M ⇐ x

// coercion
-----------------
Γ |- (M : A) :> A

Γ, [x == T], M :> x |- M :> T
-----------------------------
Γ, x == T; Δ; |- M :> x

-------------------
Γ, M :> x |- M :> x

// universe
----------------
Γ |- TypeType

// functions
Γ, x : A |- BType
------------------------
Γ |- (x : A) -> BType

|Γ|, x : A |- MB
--------------------------
Γ |- x => M(x : A) -> B

Γ |- M(x : A) -> B  Γ |- NA
---------------------------------
Γ |- M NB[x := N]

// intersection
Γ, x : A |- BType
-----------------------
Γ |- (x : A) & BType

Γ |- (M : S) :> A  Γ |- (M : S) :> B[x := A]
--------------------------------------------
Γ |- (M : S) :> (x : A) & B

Γ |- M(x : A) & B
--------------------
Γ |- MA

Γ |- M(x : A) & B
--------------------
Γ |- MB[x := M]

// mutual fixpoint
Γ, x : A | Δ, x == M |- KT
-------------------------------------------
Γ | Δ |- x : A; KT[x := x : A; x = M; x]

Γ, x : A |- KT
-------------------------------------------
Γ | Δ |- x : A; KT[x := x : A; x = M; x]


Γ, x : B | Δ, x == M |- KT  Γ, x : A |- x :> B
------------------------------------------------- // ?
Γ, x : A | Δ |- x : B; KT


Γ | Δ |- A(x : A) & B
Γ, x : A | Δ |- MB  Γ, x == M | Δ |- e ⇒ T
---------------------------------------------
Γ, x : A | Δ, x == M |- x = M; KT


Context ::= Γ | Δ
Variable ::= x | y
Term ::= M | N
Type ::= A | B
Pattern := P | Q
Constraint ::= C | D

Rule :=
  | Γ |- MA // infer type
  | Γ |- MA // check type
  | Γ |- PA; Δ // infer pattern
  | Γ |- PQ; Δ // check pattern
Γ |- MA == Γ |- M ⇐ _x

Γ |- MA // infer type
Γ |- MA // check type

Γ |- PA; Δ // infer pattern
Γ |- PQ; Δ // check pattern



(∃_A. C); Γ |- M : _A
-------------------------------
C; Γ |- (M : B)B; C[_A := B]

(∃_a. C); (Γ, x : _a) |- MB
-----------------------------
Γ; C |- x => M(x : A) -> B

Bool : Type;
true : Bool;
false : Bool;

Bool = (b : Bool) & (P : Bool -> Type) -> P true -> P false -> P b;
true = (P : Bool -> Type) => (x : P true) => (y : P false) => x;
false = P => x => y => x;

Γ |- M[x := K]N[x := K] : A[x := K]
--------------------------------------
Γ, x == K |- MN : A

Γ, [x == K], (M : S) :> T |- (M : S) :> T
-----------------------------------------
Γ, x == K |- (M : S) :> x

Γ |- (M : S) :> A  Γ |- (M : S) :> B[x := A]
--------------------------------------------
Γ |- (M : S) :> (x : A) & B



T_true(P : Bool -> Type) -> P true -> P false -> P true;
Γ |- (true : T_true) :> Bool
Γ, (true : T_true) :> Bool |- (true : T_true) :>
  (b : Bool) & (P : Bool -> Type) -> P true -> P false -> P b
Γ, (true : T_true) :> Bool |- (true : T_true) :>
  (P : Bool -> Type) -> P true -> P false -> P true

Γ |- M[x := K]N[x := K]
-------------------------- // equality
Γ, x == K |- MN : A

[] |- (unit : (P : Unit -> Type) -> P unit -> P unit) :> Unit
(unit : (P : Unit -> Type) -> P unit -> P unit) :> Unit :: [] |-
  (unit : (P : Unit -> Type) -> P unit -> P unit) :> (u : Unit) & (P : Unit -> Type) -> P unit -> P u
(unit : (P : Unit -> Type) -> P unit -> P unit) :> Unit :: [] |-
  (unit : (P : Unit -> Type) -> P unit -> P unit) :> (P : Unit -> Type) -> P unit -> P unit

(x : A) => (x :> B) => _;
(x : Bool, y : Int) === (y : Int, x : Bool)
incr : Nat -> Nat;

a = 1;

incr = x => incr x;

Color : Type;
is_primary : (color : Color) -> Prop;

Color =
  | Red
  | Green
  | Blue
  | Secondary(left : Color & is_primary left, right : Color & is_primary right);
is_primary color = color == Red || color == Green || color == Blue;

// TODO: is removing those locks okay?
|Γ| |- S <: T
----------------- // subtype
Γ |- (M : S) :> T

----------------- // refl
Γ |- (M : S) :> S

// TODO: what if arrow is a variable that can be expanded by equality
Γ |- (M : S) :> T
--------------------------------------------
Γ |- (x => M : (x : A) -> S) :> (x : A) -> T

Γ, [x == K], (M : S); dirty :> T |- (M : S) :> T
-----------------------------------------
Γ, x == K |- (M : S) :> T

Γ, [x == K], (M : S); dirty :> T |- (M : S) :> T
-----------------------------------------
Γ, x == K |- (M : S) :> x

Γ |- (M : S) :> A  Γ |- (M : S) :> B[x := A]
--------------------------------------------
Γ |- (M : S) :> (x : A) & B

Γ |- AB
--------------------
Γ |- M(x : A) & B


Γ | • | • |- MN : A
---------------------- // enters equivalence
Γ |- MN : A

// expand once in each side
Γ, x == M | L, x | R |- M == N : A
---------------------------------
Γ, x == M | L    | R |- x <: N : A

Γ, x == M | L | R, x |- M <: N : A
---------------------------------
Γ, x == M | L | R    |- x <: N : A

// expand while one of the sides is an annotation
Γ, x == M | L, x | • |- MN : A
---------------------------------
Γ, x == M | L, x | • |- x ≡ N : A

Γ, x == N | • | R, x |- MN : A
---------------------------------
Γ, x == N | • | R, x |- M ≡ x : A

// short circuits, aka, theorems
x ∉ L  x ∉ R
----------------------
Γ | R | E |- x ≡ x : A

----------------------
Γ | • | E |- x ≡ x : A

----------------------
Γ | R | • |- x ≡ x : A

Macabeus

incr = (x : Nat) => x + 1;
x = (
  (y : A) = 1;
  y + 1
);

map : <A, B>(f : (x : A) -> B, l : List<A>) -> List<B>;

incr = x => x + 1;

map = (f, l) =>
  l
  | [] => []
  | [el, ...tl] => [f(el), ...map(f, tl)];

id : <A>(x : A) -> A
  = <A>(x : A) => x;

id_inter :
  (id_nat : ((x : Nat) -> Nat)) &
  (id_string : ((x : String) -> String)) = id;

x : Nat = id_inter 1;
y : String = id_string "a";

(n : Nat & n != 0) => n + 1

Status =
  | (tag == "valid")
  | (tag == "banned", content : String);

Status =
  (tag : Bool, ...(tag | true => (...) | false => (..., content : String)));

  | (tag == "valid", content : ())
  | (tag == "banned", content : String);

R = (...,y : Nat);
Tuple = (R : Row) => (x : Nat, ...R);

Status =
  (valid : Bool, content : valid | true => () | false => String);

(x : Status) =>
  x
  | ("valid", ()) => 0
  | ("banned", _reason) => 1;

Bool : Type;
true : Bool;
false : Bool;

Bool = (b : Bool) & (P : Bool -> Type) -> P true -> P false -> P b;
true = (P : Bool -> Type) => (x : P true) => (y : P false) => x;
false = (P : Bool -> Type) => (x : P true) => (y : P false) => y;



Nat : {
  @Nat : Type;

  one : Nat;
  add : (n : Nat, m : Nat) -> Nat;
  sub : (n : Nat, m : Nat) -> Nat;
} = {
  @Nat = Int;
};

User = {
  id : Nat;
  name : String;
};

A = { x : Nat; } & { y : Nat };

Status =
  (valid : Bool) & valid
    | true => (valid == true)
    | false => (valid == false, content : String);

(valid : Bool) & (valid == true)

(valid : Bool) & (valid == false, content : String)

x : (!valid : Bool) = (valid = true);

x : (x : Nat, y : Nat)

sum = (!x : Nat, !y : Nat) => x + y;
// TODO: warning
x = sum (y = 2, x = 1);

(x : Nat & x == 1) => x + 1;

Show = {
  A : Data;
  show : (x : A) -> String;
};

<Show_Nat : Show<Nat>> = _;

(x : Nat) => x.show();

show = <A : Show>(x : A) => x.show();

x = show<Nat, Show_Nat>(1);

id = <A : Type> =>(x : A) => x.
x : Nat = id(1);
id = (A : Type) => (x : A) => x.
x : Nat = id(Nat)(1);


Point = (<A>, x : A, y : A);
id = (<A>, x : A) => x.

x = id(1);
incr = (x : Nat) => Nat.add(x, Nat.one);

id x = x;
id(x : Nat) : Nat;


f : () -> Nat ~ IO = () : Nat => ;
(x : Nat) = (f() : Nat ~ IO);

List : {
  @List(A : Data) : Data;

  length<A>(l : List A) : Nat ~ IO;
  length<A>(l : List A) : Nat ! IO;
  length<A>(l : List A) : Nat # IO;
  length : <A>(l : List A) -> Nat;
  length : <A>(l : List A) -[IO]> Nat;

  length : <A>(l : List A) -> Nat;
  map : <A, B>(f : (x : A) -> B, l : List A) -> List B;
  filter : <A>(f : (x : A) -> Bool, l : List A) -> List A;
} = _;

Type : Type;
Data : Type;
Prop : Type;
Resource : Type;
Object : Type;
Dynamic : Type;

[@teika { mode = "dynamic"; }]
x = 1;
a = x 2;

univalence : (iso : A =~= B) -> A == B;

A =~= B : Type
A == B : Prop

f : _ = _;
g = rewrite sort_into_quick_sort f;

S = <A, B>(x : A, y : B) -> A;
T = <A, B>(x : A, y : B) -> B;

A = { A : Data; x : Nat; y : String; };
B = { A : Data; y : String; x : Nat; };
C = { x : Nat; y : String; A : Data; };

(g : T) => g(2, 1);
Socket : {
  @Socket : Resource;
} = _;

Id : (A : Data) -> Data = (A : Data) => A;

a : (x : Nat, y : Nat) = (
  x : Nat;
  y : Nat;
  x = y,
  y = 1,
);



A | B | ...R

f = x => (
  print x : _;
)


!Nat = (
  Nat : Type;
  Nat = (A : Type) -> A -> (Nat -> A) -> A;
  Nat
);

Nat[Nat := (A : Type) -> A -> (Nat -> A) -> A]

A = (A : Type) -> A -> (Nat -> A) -> A;

Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : Unit -> Type) -> P unit -> P u;

unit : (P : Unit -> Type) -> (x : P unit) -> P unit;
unit = (P : Unit -> Type) => (x : P unit) => x;

M : Open -n(∀-x. x != n -> ftv x M == ∅)
M : Closed(∀-x. ftv x M == ∅)



// explicit substitutions
Γ, [-1 := N] |- M : Closed  Γ |- N : Closed
-------------------------------------------
Γ |- M[open N] : Closed

Γ, [+n := -1] |- M : Closed
---------------------------
Γ |- M[close +n] : Open -1

// context
Γ |- N : Closed
----------------------
Γ, [-n := N] : Context

Γ, [-n := N] |- M : Open -n
---------------------------
Γ |- M : Open -n


Γ, [close +n], [open +m] |- -1 : Closed
---------------------------------------
Γ, [close +n] |- -1 : Closed


(A : Type) -> _A -> _A
(B : Type) -> B\-1 -> B\-2

(A : Type) -> B\-1 -> B\-2


(
  x : A;
  y = x;
  x = 1;
  y + 1;
)
(
  x : A;
  [y := x];
  [x := 1];
  y + 1;
)

(
  μ : A;
  [open -1];
  [open -1]
)

incr = (x : A; x + 1);
two = incr (x = 1; );

(x : A) ->
--------


Γ, x : A | Δ, x == M |- KT
-----------------------------
Γ | Δ |- x : A; KT

Γ, x : A |- KT
-------------------------------------------
Γ | Δ |- x : A; KT[x := x : A; x = M; x]


(
  x : A;
  y = x;
  x = 1;
  y + 1;
);
(
  x : A;
  [y := x\-1];
  [x\-2 := 1];
  y\-1 + 1;
);

(
  x : A;
  [y := x\-1];
  [skip [x := 1]];
  y\-1 + 1;
);



(
  x : A;
  [y := x];
  [x := 1];
  y + 1;
)

(
  x : A;
  [y := x];
  [skip [x := 1]];
  y\-1;
)
(
  x : A;
  [y := x];
  [|x := 1];
  y\-1;
)

(
  x : () -> Never;
  x = () => x ();
  x
)

(
  x : () -> Never;
  [| x := () => x ()];
  x
)

x[| x := () => x ()]
(() => x ())[| x := () => x ()]
() => x[| x := () => x ()] ()
() => x[| x := () => x ()] ()
y[skip [x := 1]][y := x]
y[y := x][x := 1]


(A : Prop) => (x : A) => (y : A) => (refl : x == y)

(
  x : A;
  [|y := x; x := 1];
  y
)
y[|y := x; x := 1]
x[|y := x; x := 1]
1[|y := x; x := 1]

Term := n | λM | M N | M[S];
Subst := M | id | S1 . S2 | fix S;


(1)[M] ~> M
(1 + n)[M] ~> n
(n)[id] ~> n
(n)[fix S] ~> (n)[S . fix S]


(1)[M . S] ~> M[S]
(1 + n)[M . S] ~> (n)[S]
(n)[id . S] ~> (n)[S]
(n)[fix S1 . S2] ~> (n)[S1 . fix S1 . S2]


(n)[M . S] ~>
(n)[fix S] ~> n[S][fix S]

(λM)[S] ~> λM[S]
(M N)[S] ~> M[S] N[S]

M[fix S1][S2]

M[s1][s2]


(
  x : () -> Never;
  [fix [x := () => x ()]];
  x
)
(
  x : Nat;
  [y := x];
  [|y := x; x := 1];
  y
)

(A = Int; (x : A) -> A)

Γ, x == N |- MT
-------------------
Γ |- M(x = N; T)

M : (A : Type; A = Int; (x : A) -> A);
----------------------------
M N : (A : Type; A = Int; A)

Γ, x == M |- K : B
----------------------------
Γ |- (x = M; K) : (x = M; B)

----------------------------
Γ |- (x = M; K) ~> K[x := M]


Term = | x\+l | x\-i | x => M | M N | M[S];
Subst = | open M | close x\+n;

(x => M) N ~> M[open M] // beta

x\-1[open M] ~> M
x\-(1 + i)[open M] ~> x\-i

x\+l[close x\+n] ~> x\+l
x\+l[close x\+l] ~> x\-1

x\+l[open M] ~> x\+l
x\-i[close x\+l] ~> x\-(1 + i)

(x => M)[S] ~> x => M[open x\+l][S][close x\+l]
(M N)[S] ~> M[S] N[S]


(x => \-1 \-2)[open t]
x => (\-1 \-2)[open x\+l][open t][close x\+l]
x => \-1[open x\+l][open t][close x\+l] \-2[open x\+l][open t][close x\+l]
x => \-1 t

(x => \-1 \+3)[close +3]
x => (\-1 \+3)[open x\+l][close +3][close x\+l]
x => \-1 \-2

O(n)
O(n^2)

(x => M) N == M[x := N]

(x => x + 1) 2 == (x + 1){x := 2} == 2 + 1 == 3

(x => x + 1) 2 == (x + 1)[x := 2] == x[x := 2] + 1[x := 2] == 2 + 1


(λ\-1 + 1) 2 == (\-1 + 1)[2] == \-1[2] + 1[2] == 2 + 1


type F<A> = A -> A;

(x => M) N


Term = | x\+l | x\-i | x => M | M N | M[S];
Subst = | open M | close;

(x => M) N ~> M[open M] // beta

x\-1[open M]; l ~> M ;
x\-(1 + i)[open M]; l ~> x\-i; l

x\+l[close]; m ~> x\+l; m
x\+l[close]; l ~> x\-1; l

x\+l[open M]; m ~> x\+l; m
x\-i[close]; m ~> x\-(1 + i); m

(x => M)[S]; l ~> x => M[open x\+l][S][close]; (1 + l)
(M N)[S]; l ~> M[S] N[S]; l


0 |- x => +1[close]

Term = | x\+l | x\-i | x => M | M N | M[S];
Subst = | open M | close;

(x => M) N ~> M[open M] // beta

x\-1[open M]; l ~> M ;
x\-(1 + i)[open M]; l ~> x\-i; l

x\+l[close]; m ~> x\+l; m
x\+l[close]; l ~> x\-1; l

x\+l[open M]; m ~> x\+l; m
x\-i[close]; m ~> x\-(1 + i); m

(x => M)[S]; l ~> x => M[open x\+l][S][close]; (1 + l)
(M N)[S]; l ~> M[S] N[S]; l

M[x := y]
M[y := x]


M[3]

1 ~> 3
2 ~> 1
1 + n ~> n


M[3][s] == M

M[3][shift . 1] == M

1 ~> 2
2 ~> 3
3 ~> 1
n ~> 1 + n   n > 3


M[open y][close y] == M

2[2][lift 1] == 2
1 == 2


M[-2] // -1 -> -2

[-1 := +5]
[+5 := -1]

Explicit Substitution

Concrete = no meta variables
Locally closed = no shifting or open
Closed = no shifting, open or close


(f : (x : A : Prop) -> Nat) 0 == (f : (x : A : Prop) -> Nat) 1

Γ |- N[x := M]
-------------------
Γ |- x := M; N



List(A) =
  | Nil
  | Cons(el : A, tl : List(A));


x : List(Nat)
x = Cons(1, x)


Term : Data;
Term =
  | var x
  | abs (M : Term)
  | app (M : Term) (N : Term);

[M] |- app (var 1) (var 1)

Context : Data;
Term(Γ : Context) : Data;

Term =
  | var : <Γ>(n) -> Term(Γ :: n)
  | abs : <Γ>(M : Term()) -> Term()
  | app (M : Term) (N : Term)



Type : Data;
Type =
  | var(binder : Nat)
  | forall(body : Type);


Type : Data;
Binder : (x : Type) -> Data;

Type =
  | arrow (param : Type) (body : Type)
  | var (x : Type & Binder x)
  | forall (body : Type)
  | exists (body : Type);
Binder = x
  | arrow _ _ | var _ => Never
  | forall _ | exists _ => Unit;

id : Type;
id = forall (app (var id) (var id));




Type : Data;
Binder : Data;

Type =
  | arrow (param : Type) (body : Type)
  | var (x : Type & Binder x)
  | forall (body : Type)
  | exists (body : Type);
Binder = x
  | arrow _ _ | var _ => Never
  | forall _ | exists _ => Unit;


forall : (b : Binder) -> _;


id : Type;
id = forall (id => app (var id) (var id));


Type : Data;
Binder : Data;

Context : Data;
Valid : (Γ : Context, n : Nat) -> Prop;
get : <Γ>(n : Nat & Valid (Γ, n)) -> Binder;

Type =
  | arrow (param : Type, body : Type)
  | var : (x : Binder) -> Type = k => n => k (get n)
  | forall (body : Type)
  | exists (body : Type);
Binder = (x : Type & x
  | arrow _ _ | var _ => Never
  | forall _ | exists _ => Unit);

Context = List Binder;
Valid = (Γ, n) => List.length Γ > n;
get = _;



id = forall (arrow (var ))


Type : Data;
Binder : (x : Type) -> Data;

Type =
  | arrow (param : Type) (body : Type)
  | var (x : Type & Binder x)
  | forall (body : Type)
  | exists (body : Type);
Binder = x
  | arrow _ _ | var _ => Never
  | forall _ | exists _ => Unit;

id : Type;
id = forall (app (var id) (var id));



Type : Data;
Binder : (x : Type) -> Data;

arrow


Teika

// let
x = 1;

f = () => x;

// shadowing
x = x + 1;

// nested-let
z = (
  y = x + 1;
  y + 1
);

// infered function
incr = x => x + 1;

// annotated function
double = (x : Nat) => x * x;

// type alias
My_nat = Nat;
triple : (x : My_nat) -> Nat
  = x => x * x * x;

// type constructor
Id = (A : Data) => A;
a : Id(Nat) = 1;

// hoisting
fib : (n : Nat) -> Nat;
fib = n =>
  n
  | 0 => 0
  | 1 => 1
  | n => fib(n - 1) + fib(n - 2);

// polymorphism
id = <A>(x : A) => x;

// properties
div = (n : Nat, m : Nat & m >= 0) => _;

checked_div = (n, m) : Option(Nat) =>
  m >= 0
  | true => Some(div(n, m))
  | false => None;

// universes
(Type l : Type (1 + l)); // univalence
(Prop l : Type l); // irrelevance
(Data l : Type l); // UIP
(Resource l : Type l); // linear
(Object l : Type l); // subtyping
(Dynamic l : Type l); // dynamic

dup = (sock : Socket) => (sock, sock);

// modules
Nat : {
  @Nat : Data;
  zero : Nat;
  one : Nat;
  add : (n : Nat, m : Nat) -> Nat;
} = _;

incr = (n : Nat) => Nat.add(n, Nat.one);

// effects
print : (msg : String) -[IO]> () = _;
parse : (data : String) -[Error]> Nat = _;
print : (data : Nat) -> String = _;
read : (file : String) -[IO]> (data : String) = _;
write : (file : String, data : String) -[IO]> () = _;

read_incr_and_write_back = file =[IO | Error]> (
  value = read(file);
  value = parse(value);
  value = value + 1;
  write(value);
);

loop : () -[Loop]> ();
loop = () => loop();

// intersection types
Strict_nat = (n : Nat) & n >= 0;

// union types
Either = (A : Data, B : Data) =>
  | (tag == "left", content : A)
  | (tag == "right", content : B);

// inductive types
Bool : Data;
true : Bool;
false : Bool;

Bool = (b : Bool) & <P>(then : P true, else : P false) -> P b;
true = (then, else) => then;
false = (then, else) => else;

Resource + Sealed types

// possible future
Bool = | true | false;

Explicit Substitution

Term =
  | x      | M[x := N]
  | x => M | M N;

(x => M) N == M[x := N] // beta

x[x := M] == M
x[y := M] == x

(x => M)[x := N] == x => M
(x => M)[y := N] == x => M[y := N]
(M N)[x := K] == M[x := K] N[x := K]


Term =
  | n  | M[S]
  | λM | M N
Subst = M | ⇑S;

(λM) N == M[N] // beta

0[M] == M
(1 + n)[M] == n

0[S] == 0
(1 + n)[S] == n[]

(x => M)[x := N] == x => M
(x => M)[y := N] == x => M[y := N]
(M N)[x := K] == M[x := K] N[x := K]



Term =
  | x      | M[x := N]
  | x => M | M N;

Term =
  | x      | M[...(x := N)]
  | x => M | M N;

----------------------- // beta
(x => M) N ~> M[x := N]

x[x := N] ~> N
x[y := N] ~> x

(x => M)[x := N] ~> x => M
(x => M)[y := N] ~> x => M[y := N]

(M N)[x := K] ~> M[x := K] N[x := K]


(M N)[x := K1][y := K2]
(M N)[x := K1; y := K2]



Term =
  | n  | M[S]
  | λM | M N
Subst = M | ⇑S;

(λM) N == M[N] // beta

0[M] == M
(1 + n)[M] == n

0[S] == 0
(1 + n)[S] == n[S]

(λM)[S] == λM[S]
(M N)[S] == M[S] N[S]


_ x == x + 1
_ x == (y => y + 1) x == _k[y := x] == x + 1

_k[y := x] == x + 1
_k[y := x][x := y] == (x + 1)[x := y]
_k == y + 1


(y => y + 1) x == (y + 1)[y := x] == x + 1



Term =
  | n  | M[S]
  | λM | M N
Subst = M | ⇑S;

(λM) N == M[N] // beta

0[M] == M
(1 + n)[M] == n

0[S] == 0
(1 + n)[S] == n[S]

(λM)[S] == λM[S]
(M N)[S] == M[S] N[S]




Term =
  | x      | M[x := N]
  | x => M | M N;

(x => M) N == M[x := N] // beta
M[x := N] == M{x := N}


Term =
  | x      | _X
  | x => M | M N
  | M[x := N];

(x => M) N == M[x := N] // beta
M[x := N] == M{x := N}    fm(M) == ∅
M[x := N] == M{x := N}[[x := N]]    fm(M) != ∅

x[x := M] == M
_X[x := M] == _X

(x => M)[y := N] == x => M[y := N]
(M N)[x := K] == M[x := K] N[x := K]


f = x => x + 1;
f 1



Term =
  | n  | M[S]
  | λM | M N
Subst = M | ⇑S;

(λM) N == M[N] // beta

0[M] == M
(1 + n)[M] == n

0[S] == 0
(1 + n)[S] == n[S]

(λM)[S] == λM[S]
(M N)[S] == M[S] N[S]

At a distance

Term (M, N) = x | x => M | M N;

(x => M) N |-> M{x := N} // beta




Term (M, N) = x | x => M | M N | M[x := N];

(x => M) N |-> M[x := N] // beta

x[x := N] |-> N
(x => M)[y := N] |-> x => M[y := N]
(M N)[x := K] |-> M[x := K] N[x := K]

L = _ | L[x := M]
C = Term with single hole




(let x = M in _)<x + 1>
L<x => M> N == L<M[x := N]>

L<x => M> N == L<M[x := N]>


(x => M)[...(x := _)] N




(x => x + x) 1
(x + x)[x := 1]
(_ + x)[x][x := 1]
(_ + x)[1][x := 1]
(1 + x)[x := 1]
(1 + _)[x := 1]
(1 + 1)[x := 1]
(1 + 1)


Term (M, N) = _ | x | x => M | M N | M[x := N]
L = _ | L[x := M]
C = Term with single hole

// rewrite
L<x => M> N  |-> L<M[x := N]> // dB
C<x>[x := M] |-> C<M>[x := M] // ls
M[x := N]    |-> M if x ∉ M // gc

// plug
_<M>           == M
(x => C)<M>    == x => C<M>
(C N)<M>       == C<M> N
(N C)<M>       == N C<M>
(C[x := N])<M> == C<M>[x := N]
(N[x := C])<M> == N<[x := C<M>]>


// equiv
(y => M)[x := N]  == y => M[x := N]    if y ∉ fv(N)
(M N)[x := K]     == M[x := K] N       if x ∉ fv(N)
M[x := N][y := K] == M[x := K][x := N] if y ∉ fv(N) && x ∉ fv(K)

(x => x + x) 1
(x + x)[x := 1]
(_ + x)<x>[x := 1]
(_ + x)<1>[x := 1]
(1 + x)[x := 1]
(1 + _)<x>[x := 1]
(1 + 1)[x := 1]
(1 + 1)



Term (M, N) = _ | n | λM | M N | M[N] | M[]
L<K> = K | L<K>[M]
C = Term with single hole

// rewrite
L<λM> N     |-> L<N[M]> // dB
C<0>[M]     |-> C<M[]>[M] // ls
M[x]        |-> M{} <=< 0fv(M) // gc

// plug
_<M>     == M
(λC)<M>  == λC<↑M>
(C N)<M> == C<M> N
(N C)<M> == N C<M>
C[N]<M>  == C<M[]>[N]
N[C]<M>  == N[C<M>]


// example
(λλ0 1) 1 0

(λλ0 1) x f
(λ0 1)[x] f
- // ls
(λ0 _)<0>[x] f
(λ0 _)<↑x>[x] f
(λ0 ↑↑x)[x] f
(λ0 ↑x) f
(0 ↑x)[f]
(_ ↑x)<0>[f]
(_ ↑x)<↑f>[f]
(↑f ↑x)[f]
(f x)
- // dB
(0 1)[f][x]
(_ 1)<0>[f][x]
(_ 1)<f>[f][x]
(f 1)[f][x]
-- // ls
-- // gc
(↑f 1)[f][x]
(f 0)[x]
(f _)<0>[x]
(f _)<x>[x]
(f ↑x)[x]
(f x)
(f ⇑x)[x]
(f ⇑x)



(λλ0 1) 1 f
(λ0 1)[1] f
- // ls
(λ0 _)<0>[1] f
(λ0 _)<1>[1] f
(λ0 2)[1] f
(λ0 1) f ;; g
(0 ⇑x)[f]
(_ ⇑x)<0>[f]
(_ ⇑x)<f>[f]
(f ⇑x)[f]
(f ⇑x)

(λ0 1)[x] f

(_ 1)<0>[x][f]
(_ 1)<0>[x][f]



(x = 1) >=> x + 1
(x + 1) <=< (x = 1)
(x = 1>; x + 1)
(x + 1<; x = 1)




Term (M, N) = x | x => M | M N | M[x := N];
L<K> = K | L[x := M]
C<K> = K | x => C | C N | M C | C[x := N] | M[x := C]

L<x => M> N  |-> L<M[x := N]> // dB
C<x>[x := M] |-> C<M>[x := M] // ls
M[x := M]    |-> M <=< x ∉ fv(M) // gc


(M N)[x := K] == M[x := K] N[x := K]
M[x := y][y := x] == M[x := y[y := x]; y := x]


[x := K] |- M N
  [x := K] |- M
  [x := K] |- N
(x => y => M) N K
(y => M)[x := N] K


L<K> = K[x := N]
L<y => M> K
L<M[y := K]>

M[y := K][x := N]


(x + y)[y := K][x := N]
(x + _)<y>[y := K][x := N]
(x + _)<K>[y := K][x := N]
(x + K)[y := K][x := N]
(x + K)[x := N]
(_ + K)<x>[x := N]
(_ + K)<N>[x := N]
(N + K)[x := N]
(N + K)


_<x + y>[y := K][x := N]
_<>


(_ + x)<x>[x := N]
(_ + x)<N>[x := N]
(N + x)[x := N]
(N + _)<N>[x := N]
(N + N)[x := N]
(N + N)


(x x y)[y := K][x := N]

_<x x y>[x := N][y := K]
(_ y)<x x>[x := N][y := K]
(_ y)<_ x><x>[x := N][y := K]
(_ y)<_ x><N>[x := N][y := K]
(_ y)<N x>[x := N][y := K]
(_ y)<N _><x>[x := N][y := K]
(_ y)<N _><N>[x := N][y := K]
(_ y)<N N>[x := N][y := K]
(N N _)<y>[x := N][y := K]


L<K<M>> vs L<K>
L[x := N]<K<x>> |-> K<N> // fast



L[x := N]<K<x>> |-> L[x := N]<K<N>> // use

L<K<x => M>> |-> L<K<x => _><M>>
L<K<M N>>    |-> L<K<_ N><M>>
L<K<_ N><M>> |-> L<K<M _><N>>

// plugging
_<M>         |-> M
(x => C)<M>  |-> x => C<M>
(C N)<M>     |-> C<M> N
(M C)<N>     |-> M C<N>
C[x := N]<M> |-> C<M>[x := N]
M[x := C]<N> |-> M[x := C<N>]

Linear Substitution Calculus

Term (M, N) = x | x => M | M N | M[x := N];
L<K> = K | L[x := M]
C<K> = K | x => C | C N | M C | C[x := N] | M[x := C]

L<x => M> N  |-> L<M[x := N]> // dB
C<x>[x := M] |-> C<M>[x := M] // ls
M[x := M]    |-> M <=< x ∉ fv(M) // gc

L<K<x>>[x := N] |-> L<>

L<K<x => M>> |-> L<K<x => _><M>>
L<K<M N>> |-> L<K<_2 _1><N><M>>>

L, x := N |- x :: K
-------------------
L, x := N |- K<N>

L |- x => x :: _
L |- x :: x => _ :: _

L<_1<x => x>>
L<_1<x => _1><x>>>

L<K<M>> vs L<K>



K<x x>[x := N]
K<_ x><x>[x := N]
K<_ x><N>[x := N]
K<N x>[x := N]
K<N _><x>[x := N]
K<N _><N>[x := N]
K<N N>[x := N]


M :: K == K<M>

(x x :: K)[x := N]
(x :: _ x :: K)[x := N]
(N :: _ x :: K)[x := N] // ls
(N x :: K)[x := N]
(x :: N _ :: K)[x := N]
(N N :: K)[x := N] // ls
(K<N N>)[x := N]

K<_ x><N>[x := N]
K<N x>[x := N]
K<N _><x>[x := N]
K<N _><N>[x := N]
K<N N>[x := N]


L<K<x>>[x := N] |-> L<K<N>>[x := N] // ls
L
K<_ x><N>[x := N]

L<K<(x => M) N>> |-> L<K<M[x := N]>> // dB
L<K<x => M>> |-> L<(x => _)<x>>

L<K<M N>> |-> L<K<M N>>
Γ |- M N :: K |-> Γ |- M :: _ N :: K // Lapp
Γ |- M N :: K |-> Γ |- N :: M _ :: K // Rapp


Γ |- M :: _ N :: K  bv(Γ) ∩ fv(M) != ∅ // TODO: this is bad
-------------------------------------- // left-apply
Γ |- M N :: K

Γ |- M :: M _ :: K  bv(Γ) ∩ fv(M) == ∅
-------------------------------------- // right-apply
Γ |- M N :: K



Term (M, N) = x | x => M | M N | M[x := N];
L |- _ = _ | L[x := M]
_ :: C = _ | x => C | C N | M C | C[x := N] | M[x := C]

----------------------------------
L |- (x => M) N |-> L |- M[x := N] // dB

-------------------------------------
(x :: C)[x := M] |-> (M :: C)[x := M] // ls

x ∉ fv(M)
--------------- // gc
M[x := M] |-> M

// plugging
M :: _         == M
M :: (x => C)  == x => (M :: C)
M :: C N       == (M :: C) N
M :: N C       == N (M :: C)
M :: C[x := N] == (M :: C)[x := N]
M :: N[x := C] == M[x := (N :: C)]

// algorithm

-------------------------------------------- // ls
L, x := N |- x :: K |-> L, x := N |-> N :: K



(x x)[x := y][y := z]


// reference
Term (M, N) = x | x => M | M N | M[x := N];
L<K> = K | L[x := M]
C<K> = K | x => C | C N | M C | C[x := N] | M[x := C]

L<x => M> N  |-> L<M[x := N]> // dB
C<x>[x := M] |-> C<M>[x := M] // ls
M[x := M]    |-> M <=< x ∉ fv(M) // gc


// alternative
C<x>[x := M] |-> C[x := M]<M> // ls

C<M>[x := N] == C[x := N]<M>

// de-bruijin
Term (M, N) = _ | n | λM | M N | M[N] | M[];
Partial (_ :: C) = _ | λC | C N | M C | C[N] | M[C] | C[];
Context (L |- _) = _ | L, N;

// rewrite
L |- (λM) N :: K |-> L, N |- M :: K[] // dB
L, N |- 0 :: K |-> L |- N :: K[N] // ls
L, N |- K[] |-> L |-> K // drop

// notation
L |- K[N] == L, N |- K

// plug
M :: _   == M
M :: λK  == λ(M[] :: K)
M :: K N == (M :: K) N
M :: N K == N (M :: K)
M :: K[N] == (M[] :: K)[N]
M :: N[K] == N[M :: K]



// de-bruijin
Term (M, N) = 0 | λM | M N | M[N] | M[];
Partial (_ :: C) = _ | λC | C N | M C | C[N] | M[C] | C[];
Context (L |- _) = _ | L, N;

// rewrite
L |- (λM) N :: K |-> L, N |- M :: K[] // dB
L, N |- 0 :: K |-> L |- N :: K[N] // ls

// equiv?
L |- M[N] :: K == L, N |- M :: K[]
L, N |- M[] :: K == L |- M :: K[N]

// plug
M :: _   == M
M :: λK  == λ(M :: K)
M :: K N == (M :: K) N
M :: N K == N (M :: K)
M :: K[N] == (M :: K)[N]
M :: N[K] == N[M :: K]


L |- λM == L, 0 |- M :: λ_[];


L |- λ(M 0) == L, 0 |- M 0 :: λ_[];

x |- 1 0 :: λ_


(λ1 0)
1 0 :: λ_

M == 1
L == x

0 == 0
(1 + n) == 1[]

x, 0 |- 1 0 :: λ_[]
x, 0 |- 1 0 :: λ_[]

x, 0 |- 1 0 :: λ_[]

x, 0 |- 1 :: _ 0 :: λ_[]

x, 0 |- 0[] :: _ 0 :: λ_[]

x |- 0 :: (_ 0)[0] :: λ_[]
x |- x :: (_ 0 :: λ_[])[0]
x |- (x 0)[0] :: λ_[]
x, 0 |- (x 0) :: λ_[]

0[] ==



Term (M, N) = 0 | λM | M N | M[N] | M[];
Partial (_ :: C) = _ | λC | C N | M C | C[N] | M[C] | C[];
Context (Γ |- _) = _ | L, N;



Γ |- M[S] :: K |-> Γ, S |- M :: K


C<x>[x := M] |-> C<M>[x := M] // ls


Γ, N |- 0 :: K |-> Γ, N |- N :: K // ls

(1 + n) == n[]
A, B |- 1 :: K == A |- 0 :: _[] :: K[B]

(λM) == λ
A |- A :: _[] :: K[B]
A, B |- A[] :: K


Γ, N |- 1 + n :: K == Γ |- n :: (1 + _) :: K[N]

(1 + n :: _)[N] == (n :: 1 + _ :: _)[N]


M :: K[N] == (M :: K)[N]

(1 + n :: _)[N] == (n :: 1 + _ :: _[N])

(1 + n :: K)[N] == (n :: 1 + _ :: K)[N]

(λ_)<0>[0]

(λ_)<0>[0]

(λM)[N] == λ(M[0][N])
(λx (1 2))[0 1][1]

\0[\0 + 1]
(x + 1)[x := x + 1]

K<0[N]> == K<_<0>[N]>

K<M[S]> == K<_[S]><M>


(_ N)<M[S]> == M[S] N


(_ N)<M>[S]
M[][S]
M´

C<A>

M (_<N> _)<K>


Γ, x |- M |-> K
----------------------
Γ |- x => M |-> x => K



Γ, x := 1 |- 1 == x : Nat
--------------------------
Γ |- 1 == (x => x) 1 : Nat

Γ, 1 |- 1 == 0 : Nat
---------------------
Γ |- 1 == (λ0) 1 : Nat


Γ |-
---------------------------
Γ |- (λ0) 2 == (λ0) 1 : Nat


0[1]


Unit : Type;
Unit = (u : Unit);


x[x := N][x := K]


Pack : {
  Unit : Type;
  unit : Unit;
};
Pack = {
  Unit = (u : Pack.Unit) & (P : Pack.Unit -> Type) -> P (Pack.unit) -> P u;
  unit =
}
Unit : Type;
unit : Unit;


{ x : A; x : A; }

{ x : A; ...R }


Type l : Type (1 + l);
Data l : Data (1 + l);
Prop l : Prop (1 + l);


N == M : Prop
N =~= M : Type

A : Data;

((x : A) -> A) : Data
((x : A) -> A) : Type

id = (A : Type) => (x : A) => x;

x = id ((x : Nat) -> Nat)



x - 2 = 0

x = y
f(x) = f(y)

f(x) = 0;

0 = 1
0 * 0 = 1 * 0
0 = 0

x - 2 * 0 = 0 * 0



H === False == (P : (f : False) -> Type) -> P f
H |- False == @box((P : (f : False) -> Type) -> P f)
|- @box((P : (f : False) -> Type) -> P f) == @box((P : (f : False) -> Type) -> P f)

+P1 |- False == (P : False -> Type) -> P f
-P1 |- False == (P : False -> Type) -> P f


H === False == (P : (f : False) -> Type) -> P f

H |- False == (P : (f : False) -> Type) -> P f
[H] |- False == (P : (f : False) -> Type) -> P f




Γ, x : A === M | Δ |- M == N
----------------------------
Γ, x : A == M | Δ |- x == N

Γ | Δ, x : A === N |- M == N
----------------------------
Γ | Δ, x : A == N |- M == x

M === N
----------------------------
Γ, x : A === M | Δ |- x == N

M === N
----------------------------
Γ, x : A === M | Δ |- x == N

------------------------
Γ, x : A === M |- x == N


False == (P : False -> Type) -> P f |-
  False ==

P | P |- (P : False -> Type) -> P f == (P : False -> Type) -> P f


H |- (P : False -> Type) -> P f == False


• | False |- False == False



id
  : (A : Type) -> (x : A) -> A
  = (A : Type) => (x : A) => x;


x = id String "a";


Type l : Type (1 + l);
Data l : Type (1 + l);
Prop l : Type (1 + l);



(x : Int) => x
(x : String) => x

Γ |- M == N : B
------------------------------------
Γ |- x => M == x => N : (x : A) -> B

Γ, x : A == M | R, x | • |- M == N[x := M]
------------------------------------------
Γ, x : A == M | R, x | • |- x == N


H === x == () -> x

H | x | • |- x == () -> x
H | x | • |- () -> x == () -> x
H | x | • |- x == x

H | -x, +x | +x, -x |- x == () -> x
H | +x, -x | +x, -x |- () -> x == () -> x
H | x | x |- () -> x == () -> x


Γ, x == N |- MA
------------------
Γ |- MA[x := N]



-------------------------------------------------
Γ |- M[x := N] : A[x := N] === Γ, x := N |- M : A

Context (Γ, Δ)
Term (M, N)
Type (A, B)


Γ |- M(x : A) -> B  Γ |- NA
--------------------------------- // apply
Γ |- M NB[x := N]

Γ |- ML<(x : A) -> B>  Γ |- NL<A>tttw
--------------------------------------- // apply at a distance
Γ |- M NL<x = N; B>



Γ, x : A[Δ] |- MB[Δ]
------------------------------- // d-lambda
Γ |- x => M((x : A) -> B)[Δ]




Γ |- M((x : A) -> B)[Δ]  Γ |- NA[Δ]
----------------------------------------- // apply at a distance
Γ |- M NB[x := N][Δ]

((x : A) -> B)[Δ]
((x : A[y := y]) -> B[y := y])[y := K]
((x : A[y := K]) -> B[y := y])[y := K]
((x : A[y := K]) -> B[y := K])[y := K]

x + 1 -| Δ
(x, y) = (1, 2); N

_<x>[x := x]
n + m == add n m

Γ |- M[x := K] == N[x := K]
---------------------------
Γ, x == K |- M == N

x == 1;


x == 1 |- 2 == x + 1
|- 2 == 1 + 1
|- 2 == 2
Γ |- _
Γ; _e

C<x>[x := N] |-> C<N>[x := N]
C<0>[N] |-> C<N>[N]




Γ, x : A |- MB
-------------------------- // lambda
Γ |- x => M(x : A) -> B

Γ, x : A[L] |- MB[L]
------------------------------- // d-lambda
Γ |- x => M((x : A) -> B)[L]

------------------------------- // d-lambda
((x : A) -> B)[L] === ()

(X = Nat; (x : X) -> Nat) == (x : Nat) -> Nat

incr : (X = Nat; Y = Nat; (x : X) -> Y)
  = (x : (X =)) => x + 1;

context : []
expected : Nat
received : (X = Nat; X)

context : []
expected : Nat
received : Nat



(x => M) N |-> M[x := N] // beta

(x => M) N |-> (x = N; M) // beta

L<x => M> N |-> L<M[x := N]> // dB
C<x>[x := N] |-> C<N>[x := N] // ls


Γ, A[Δ] |- MB[⇑Δ]
-------------------- // bad-lambda
Γ |- λM(A. B)[Δ]


Γ |- M[0 : A[Δ]]B[0 : A . Δ]
-------------------------------- // d-lambda
Γ |- λM(A. B)[Δ]


Γ |- M[0 : A . Δ]B[0 : A . Φ]
-------------------------------- // d-lambda
Γ |- (λM)[Δ](A. B)[Φ]




M[0 : A . Δ]B[0 : A . Φ]
--------------------------- // d-lambda
(λM)[Δ](A. B)[Φ]

(A. B)[Δ] == (A[Δ]. B[0 : A . Δ])
(A[Δ]. B[⇑Δ])

((x : A) -> B)[Δ]
((x : A[Δ]) -> B[0 : A][Δ])[Δ]

(λ(0 == 1))[N]
(λ(0 == 1)[N])
(λ(0 == 1[N]))

----------------
Γ |- L<M> ⇐ Δ<A>

L<((x : A) -> B)> == ((x : L<A>) -> L<B>)

((x : A) -> B)[S] == (x : A[S]) -> B[S]

LC <==> LSC <==> TM
(y = K; (x => M)) N |-> (y = K; x = N; M)

(x => M) N |-> (x = N; M)

(x => x + 1) 2 |-> 2 + 1

At a Distance Typing

No Sharing

M[Γ]A[Γ]
----------------- // i-annot
(M : A)[Γ]A[Γ]

M[Γ]A[Δ]  A[Δ]B[Φ]
------------------------ // dc-infer
M[Γ]B[Φ]

----------------- // i-univ
Type[Γ]Type[Γ]

B[x : A][Γ]Type[Γ]
--------------------------- // i-forall
((x : A) -> B)[Γ]Type[Γ]

M[x : A[Δ]][Γ]B[x : A][Δ]
------------------------------- // dc-lambda
(x => M)[Γ]((x : A) -> B)[Δ]

M[Γ]((x : A) -> B)[Δ]  N[Γ]A[Δ]
------------------------------------- // di-apply
(M N)[Γ]B[x : A = N][Δ]

N[Γ]A[Δ]  M[x : A[Δ] = N][Γ]B[Φ]
-------------------------------------- // di-let
(x = N; M)[Γ]B[Φ]


N[Γ]A[Δ]  M[x : A[Δ] = N][Γ]B[Φ]
-------------------------------------- // di-let
(x = N; M)[Γ]B[Φ]

Sharing

Γ |- MA === M[Γ]A[Γ]
Γ |- MA === M[Γ]A[Γ]

Γ |- MA
---------------- // i-annot
Γ |- (M : A)A

Γ |- MA
---------- // dc-infer
Γ |- MA

Γ |- NA  Γ, x : A = N |- MB
--------------------------------- // i-let
Γ |- M[x = N]B

Γ |- NA  Γ, x : A = N |- MB
--------------------------------- // c-let
Γ |- M[x = N]B

------------------- // i-univ
Γ |- TypeType

Γ, [x : A] |- BType
------------------------ // i-forall
Γ |- (x : A) -> BType

Γ, [x : A] |- MB
-------------------------------- // i-lambda
Γ |- (x : A) => M(x : A) -> B

Γ |- M[x : A[Φ]][Δ]B[x : A][Φ]
------------------------------------ // dc-lambda
Γ |- (x => M)[Δ]((x : A) -> B)[Φ]

Γ |- M((x : A) -> B)[Δ]  Γ |- NA[Δ]
----------------------------------------- // di-apply
Γ |- M NB[x : A = N][Δ]



M[x : A[Φ]][Δ][Γ]B[x : A][Φ][Γ]
------------------------------------- // dc-lambda
(x => M)[Δ][Γ]((x : A) -> B)[Φ][Γ]

M[x : A[Δ]][Γ]B[x : A][Δ]
------------------------------- // dc-lambda
(x => M)[Γ]((x : A) -> B)[Δ]


M[x : A[Φ][Γ]][Δ][Γ]B[x : A][Φ][Γ]
------------------------------------- // dc-lambda
(x => M)[Δ][Γ]((x : A) -> B)[Φ][Γ]

M[x : A[Φ][+|Δ|]][Δ][Γ]B[x : A][Φ][Γ]
------------------------------------- // dc-lambda
(x => M)[Δ][Γ]((x : A) -> B)[Φ][Γ]

M[x : A[]][Δ][Γ]B[x : A][Φ][Γ]
------------------------------------- // dc-lambda
(x => M)[Δ][Γ]((x : A) -> B)[Φ][Γ]

Γ |- M[x : A[Φ]][Δ]B[x : A][Φ]
--------------------------------------- // dc-lambda
Γ |- (x => M)[Δ]((x : A) -> B)[Φ]


Γ, Δ |- M[↑|Δ|]A
------------------- // dc-lambda
Γ |- MA[Δ]

Γ, Δ |- M[↑|Δ|]A
------------------- // dc-lambda
Γ |- MA[Δ]

Γ, x : A |- M[⇑Δ]B
------------------------------- // dc-lambda
Γ |- (x => M)[Δ](x : A) -> B

M[⇑Δ][x : A . Γ]B[x : A . Γ]
------------------------------- // dc-lambda
(x => M)[Δ][Γ]((x : A) -> B)[Γ]


Γ, x : A[Δ] |- MB[x : A][Δ][]
--------------------------------- // dc-lambda
Γ |- x => M((x : A) -> B)[Δ]


Γ, x : A[Δ] |- MB[x : A][Δ][]
--------------------------------- // dc-lambda
Γ |- x => M((x : A) -> B)[Δ]

M[x : A[Δ]][Γ]B[x : A][Δ][][x : A[Δ]][Γ]
-------------------------------------------- // dc-lambda
(x => M)[Γ]((x : A) -> B)[Δ][Γ]

M[x : A[Δ]][Γ]B[x : A][Δ][Γ]
---------------------------------- // dc-lambda
(x => M)[Γ]((x : A) -> B)[Δ][Γ]

Γ |- NA  Γ, x : A == N |- MB[]
------------------------------------- // c-let
Γ |- x = N; MB

Γ |- MA [0]
---------------- // c-let
Γ |- (M : A)A



M[x : A[Δ]][Γ]B[x : A][Δ]
------------------------------- // dc-lambda
(x => M)[Γ]((x : A) -> B)[Δ]

Context typing

Context (Γ, Δ) := _ | Γ[x : A] | Γ[x : A := N];
Term (M, N)
Type (A, B) :=
  | (M : A) | Type | \n | x = N; M | x = N; M
  | (x : A) -> B | (x : A) => M | M N | x => M;


Γ |- MA       === M[Γ]A[Γ]
Γ |- MA[Δ]    === M[Γ]A[Δ][Γ]
Γ |- M[Φ]N[Δ] === M[Φ][Γ]N[Δ][Γ]


Γ |- MA  Γ |- A[]B[Δ]    Γ |- (M : A)A[]
----------------------------    -------------------
Γ |- MB[Δ]                   Γ |- (M : A)A

----------------
Γ |- TypeType

                      Γ |- \n ⇒ B
------------------    ------------------------
Γ[x : A] |- \0A    Γ[x : A] |- \(1 + n)B

Γ[x : A] |- BType[Δ]        Γ[x : A] |- MB[Δ]
---------------------------    -----------------------------------
Γ |- (x : A) -> BType[Δ]    Γ |- (x : A) => M(x : A) -> B[Δ]

Γ[x : A[Δ]] |- MB[y : A][Δ][]
--------------------------------- // dc-lambda
Γ |- x => M((y : A) -> B)[Δ]

Γ |- M((x : A) -> B)[Δ]  Γ |- NA[Δ]
----------------------------------------- // di-apply
Γ |- M NB[x : A := N][Δ]

Γ |- NA[Δ]  Γ[x : A[Δ] == N] |- MB[Φ]
------------------------------------------- // dr-let-infer
Γ |- x = N; MB[Φ][x : A[Δ] == N]

Γ |- NA[Δ]
---------------------------------- // dr-let-infer
Γ |- x = N; M |-> M[x : A[Δ] := N]



Nat : Type;
String : Type;



                        \n[Γ]B
--------------------    ----------------------
x\0[x : A][Γ]A[Γ]    \(1 + n)[x : A][Γ]B

M[x : A][Γ]B[Δ]
--------------------------------------
((x : A) => M)[Γ](x : A[Γ]) -> B[Δ]

M[Γ]((x : A)B)[Δ]  N[Γ]A[Δ]
------------------------------------
(M N)[Γ]B[x : A := N][Δ]


(x => x) 1
[x == 1] |- x
[x == 1] |- 1


f : (x : Nat) -> Nat;
f : (X = Nat; (x : X) -> X);

(f 1) : Nat

(f 1) : (X = Nat; X)

((x => x) : (x : Nat) -> Nat)

((
  y = 2;
  x => x
) : (x : Nat) -> Nat)

(incr : (x : Nat) -> Nat) = (
  k = 1;
  x => x + 1
);

add = n + 1 + 1 + 1 ... m
mul = n + n + n + n ... m
pow = n * n * n * n ... m

64 + 1
n + n
64 + 64

x\0[x : Nat\1][Γ]Nat\1[Γ]
----------------------------------------------------
((x : Nat\1) => x\0)[Γ](x : Nat\1[Γ]) -> Nat\1[Γ]




x\0[x : A\1]A\1
----------------------------------------
x\1[f : (y : A\2) -> A\3][x : A\1]A\1

A\1A\2[x : A\1]

f\0[f : (y : A\2) -> A\3][x : A\1]((y : A\2) -> A\3)[x : A\1]
----------------------------------------------------------------------
(f\0 x\1)[f : (y : A\2) -> A\3][x : A\1]A\3[y : A\2 := x\0][x : A\1]
-----------------------------------------------------------------------
((x : A\1) => (f : (y : A\2) -> A\3) => f\0 x\1)[Γ](x\1[y][x : Nat\1] : Nat\1)
(y => x)[x : Nat\1] : (y : _) -> Nat\2


(x : Nat\1) => x\0

[x : A] |- x\0B[Δ]
y = (x\1[y][x : Nat\1 == _] : Nat\1);

Γ[x : A] |- MB[Δ]
-----------------------------------
Γ |- (x : A) => M(x : A) -> B[Δ]

(x : Nat\1) => (x\0[x : Nat\1])

(\0[x : Nat\1] : Nat\1)
Nat\2[x : Nat\2]


x
x => M
M N


(x => y => x) == (y => x => y)
(_ => _ => \1) == (_ => _ => \1)

(x => y => x)
(x => y => z => x)

(Nat => (x : Nat\1) => y => z => (x\2 : Nat\4))


----------
Γ |- M : A

---------------------
Γ, x : A\1 |- x : A\2

----------------------
x[x : A\1][Γ] : A\1[Γ]

Γ |- A : Type  Γ, x : A |- B : Type
-----------------------------------
Γ |- (x : A) -> B : Type


------------------------------
[x : A] |- (y : A) -> A : Type

----------------------------
((y : A) -> A)[x : A] : Type


(x => x y)



                        \n[Γ]B[Δ]
-------------------     -------------------------
\0[x : A][Γ]A[Γ]     \(1 + n)[x : A][Γ]B[Δ]

// term-level
                        \n[Γ]B
-------------------     ----------------------
\0[x : A][Γ]A[Γ]     \(1 + n)[x : A][Γ]B

M[x : A][Γ]B[x : A]
--------------------------------
((x : A) => M : (x : A) -> B)[Γ]

M[(x: A[Δ]) => _][Γ]B[(x : A) -> _][Δ]
-----------------------------------------
(x => M)[Γ]((x : A) -> B)[Δ]

M[Γ]((x : A)B)[Δ]  N[Γ]A[Δ]
------------------------------------
(M N)[Γ]B[x : A := N][Δ]



------------------------------
(Γ |- x => M)(Δ |- (x : A) -> B)

-------------------------------
(x => M)[Γ]((x : A) -> B)[Δ]

(x => M : (x : Nat) -> Nat)

((
  y = 1;
  x => M
) : (x : Nat) -> Nat)

(x => M : (
  X = Nat;
  (x : Nat) -> Nat
))

-----------------------------
\0[x : A][Γ]A[][x : A][Γ]


\n[Γ]B[Δ]
-----------------------------------
\(1 + n)[x : A][Γ]B[][x : A][Δ]

M[(x : A) => _][Γ] : B[x : A][Δ]
------------------------------------- // dc-lambda
((x : A) => M)[Γ] : ((x : A) -> B)[Δ]


B[][x : A][Δ] == B[Δ]


Context (Γ) ::= _ | Γ[x : A] |;

x[x : A]


------------------- // i-head
\0[x : A][Γ]A[Γ]

\n[Γ]B[Δ]
------------------------- // i-tail
\(1 + n)[x : A][Γ]B[Δ]

M[x : A][Γ]B[x : A][Γ]
------------------------------------- // i-lambda
((x : A) => M)[Γ]((x : A) -> B)[Γ]

M[Γ]((x : A) -> B)[Δ]  N[Γ]A[Δ]
---------------------------------- // di-apply
(M N)[Γ]B[x : A = N][Δ]


MM[][x : A]


------------------- // i-head
\0[x : A][Γ]A[Γ]


n[Γ]B[Δ]
------------------------- // i-head
\(1 + n)[x : A][Γ]B[Δ]

M[x : A][Γ]B[x : A][Γ]
------------------------------------- // i-lambda
((x : A) => M)[Γ]((x : A) -> B)[Γ]

M[x : A[Δ]][Γ]B[x : A][Δ]
------------------------------------- // dc-lambda
(x => M)[Γ]((x : A) -> B)[Δ]

M[Γ]((x : A) -> B)[Δ]  N[Γ]A[Δ]
------------------------------------- // di-lambda
(M N)[Γ]B[x : A = N][Δ]


x\0[x : Nat\0][Nat : Type]Nat\0[Nat : Type]
-----------------------------------------------------------
((x : Nat\0) => x\0)[Nat : Type] : (x : Nat\0) -> Nat\0[]


Nat\0[Nat : Type] == _B[x : Nat\0][Nat : Type]
Nat\0 == _B[x : Nat\0]
Nat\0[][x : Nat\0] == _B[x : Nat\0]
Nat\0[] == _B

Nat\1[Nat\1 : Type] == _B[x : Nat\1][Nat\1 : Type]
Nat\1 == _B[x : Nat\1]
Nat\1[] == _B



f : (X = Nat; (x : Nat) -> X);


(x => x + 1 : (x : Nat) -> Nat)
((
  one = 1;
  x => x + one
) : (x : Nat) -> Nat)

(λx. λy. t) u ~ λy. ((λx. t) u)


(λy. t)[x := u] ~ λy.t[x := u]
λy. t[x := u] ~ λy.t[x := u]

(λx.t v) u ~ (λx.t) u v
(t v)[x := u] ~ t[x := u] v
(t v)[x := u] ~ t[x := u] v

(λ.t v) u ~ (λ.t) u v
(t v)[u] ~ t[u] v


Term ::= n | λM | M N | M[S];
Subst ::= N | ↓;

0[N] |-> N        // head
(1 + n) |-> n     // drop


(M N) |-> M[][N] // db
(λM)[] |-> M     // skip

Term ::= x | x => M | M N | M[x := N] | M[apply N];

x[x := N] |-> N
(y => M)[x := N] |-> (y => M[x := N])

(M N) |-> M[apply N] // beta
(x => M)[apply N] |-> M[x := N] // skip


x[apply N]

(f v)[y := u]
  f[apply v][y := u]

((x => t) v)[y := u]
  (x => t)[apply v][y := u]
  t[x := v][y := u]


Term ::= n | λM | M N | M[S];
Subst ::= N | ⇑S | ⇓S;

0[N] |-> N
(1 + n)[N] |-> n

0[S] |-> 0
(1 + n)[S] |-> n[S]

(λM)[S] |-> λM[S]

(M N) |-> M[N] // db
(λM)[S] |-> M     // skip

((λt) v)[u]
  (λt)[⇓v][u]
  t[v][u]

(λ1)[u]
(t v)[u]
  t[][v][u]


((λt) v)[u]
-
  (λt)[][v][u]
  t[v][u]

((λt) v)[u]
- t[v][u] // beta
- t[u][v] // propagation first
((x => t) v)[y := u]
- t[x := v][y := u] // beta
- t[y := u][x := v] // propagation first

λM[] |-> M // elim-lambda
M[N][] |-> M // elim-subst



λM[] |-> M // elim-lambda

λM[] |-> M // elim-lambda


λ(0[]) |-> M // skip-lambda
λ(0[]) |-> M // skip-binder

λM[] |-> M // elim-lambda
M N |-> M[][N] // weird-beta


λ0 |-> 0[]

(λ0) N |-> N

(λ0[])[N][] |-> N

(λM) N

(f 1) : (X = Nat; X)

Nat\1[Nat\1 : Type] == _B[x : Nat\1][Nat\1 : Type]
Nat\1 == _B[x : Nat\1]

Nat\1[][x : Nat\1] == _B[x : Nat\1]
Nat\1[] == _B

Nat\1[] == Nat\1[]

Nat\1[][][x : Nat\1] == _B[x : Nat\1]
Nat\1[][] == _B

Nat\1[] == _B[x : Nat\1]:= ↑
Nat\1 == _B[x : Nat\1]
Nat\1[] == _B[x : Nat\1][]
Nat\1[] == _B
Nat\1[] == _B

_B[x : Nat\1][]Nat\1[]
------------------
⇒ (x : Nat\1) ->


Nat\1[] ==

(x : Nat\1) => (x\0 : Nat\1[])

⇒
--------------------
(x : Nat\1) => \0((x : Nat\1) -> Nat\1):= ↑

MK[][]
-------------------------
x => M((A : Type) -> B)[][]



Nat\1[] == Nat\1[]

Nat\1 == _B[x : Nat\1]
Nat\1[][x : Nat\1] == _B[x : Nat\1]
Nat\1[] == _B

Nat\1[] == _B[x : Nat\1]

Nat\1 == _B[x : Nat\1][]

received : Nat\1[Δ]
expected : _B[x : Nat\1][Δ]

_B := Nat\1[]


Term (M, N) ::= 0 | λM | M N | M[S];
Subst (S) ::= N | ↑ | ↓;

0[N] |-> N

0[][N] |-> n
0[N][] |-> n

0[S] |-> 0
0[S] |-> 0

M[][S] |-> M[S][]
M[][S] |-> M[S][]


M N |-> M[N] // Beta

(λM)[S] |-> M[S] // Skip


0[1][]
n[] |-> (1 - n)


0[1][] |-> 1[] |-> 0
0[2][] |-> 2[] |-> 0

M[][S] |->
M[S][] |->

(λM)[] == λM[⇑↓]
n[]


(λ0[]) (λλ0)
(λ0[])[][λλ0]
0[][λλ0]
0[][λλ0] ? 0[λ0]

M[S][]

(λ0[]) (λλ0)
(λλ0)[]
(0)[][N]


M[][N] |-> M // drop


(1 + n)[N] |-> n // drop



(λM)[N] |-> λM[N]
(λM)[S] |-> λM[⇑⇑S]


((λt) v)[u]
- t[v][u] // beta




(λ0)[N] |-> λ0
(λ1)[N] |-> λN
(λ2)[N] |-> λ1


Term (M, N) ::= 0 | λM | M N | M[S];
Subst (S) ::= N | ↑ | →;

M N |-> M[][N]l
(λM)[] |-> M

M[N][] |-> M

M N



(λM)[N] |->

2[N]
M[N][] |->

M[][N] |->



(λ0)[N] |-> λ0
(λ1)[N] |-> λN[]
(λ2)[N] |-> λ1

Term (M, N) ::= 0 | λM | M N | M[S];
Subst (S) ::= N | ↑ | →;

De-bruijin + sharing

Context (Γ) ::= _ | Γ, x : A | Γ, x : A = N;
Term (M, N)
Type (A, B) ::=
  | (M : A) | Type | \n | x = N; M | x = N; M
  | (x : A) -> B | (x : A) => M | M N | x => M | M[Δ];
Subst (Δ, Φ) ::= | M | Δ[x : A = N] | _[]
Variable (n) ::= 0 | 1 + n

Γ |- MA[n]       === M[Γ]A[n][Γ]
Γ |- MA[Δ][n]    === M[Γ]A[Δ][n][Γ]
Γ |- M[Φ]N[Δ] === M[Φ][Γ]N[Δ][Γ]

Γ |- A : Prop
--------------
Γ |- MN : A

Γ |- MA[↑n]


Γ |- MA  Γ |- A[]B[Δ][n]    Γ |- (M : A)A[][0]
-------------------------------    ----------------------
Γ |- MB[Δ][n]                   Γ |- (M : A)A

----------------
Γ |- TypeType


Γ, x : A == N :
------------------------- // forget
Γ, x : A == N |- Γ, x : A

--------------------- // i-head
Γ, x : A |- \0A[]

Γ |- \n ⇒ B
--------------------------- // i-tail
Γ, x : A |- \(1 + n)B[]

Γ, x : A |- MB[Δ | n]
--------------------------------------- // i-lambda
Γ |- (x : A) => M(x : A) -> B[Δ | n]

Γ, x : A |- BType[• | 0]
------------------------------- // i-forall
Γ |- (x : A) -> BType[• | 0]

Γ, x : A |- MB[Δ | n]
--------------------------------------- // i-lambda
Γ |- (x : A) => M(x : A) -> B[Δ | n]

Γ, x : A[Δ] |- MB[y : A][Δ | 1 + n]
---------------------------------------- // dc-lambda
Γ |- x => M((y : A) -> B)[Δ | n]

Γ |- M((x : A) -> B)[Δ | n]  Γ |- NA[Δ | n]
------------------------------------------------- // di-apply
Γ |- M NB[x : A = N][Δ | n]

Γ |- NA[Δ]  Γ[x : A[Δ] = N] |- MB[Φ]
------------------------------------------- // dr-let-infer
Γ |- x = N; MB[Φ][x : A[Δ] == N]


--------------------------------- // i-head
Γ, x : A | n |- x\+, x : A| ⇒ A

Γ |- \n ⇒ B[Δ | n]
----------------------------------- // i-tail
Γ, x : A |- \-(1 + n)B[Δ | 1 + n]


(A : Type) => (x : _B) => (x : B\0 : A\1)
(x : _B) => (A : Type) => (x : A\0)

-----------------------------
Γ | Δ |- _x ≡ N -| Δ, _x := N

-----------------------------
Γ | Δ |- M ≡ _x -| Δ, _x := M

Γ |- MB  Γ |- BA -| Δ
---------------------------
Γ |- MA -| Δ


Γ, x | y : A |- M[open +n]N[open +n]
------------------------------------------
Γ |- ((x : A) => M)((y : A) => N)[Φ]


Γ, x : A |- BK
-------------------------------------
Γ |- (x : A) -> B : K

incr = x => x + 1;
n = incr 1;


x : Nat;
x = x;

x

x[x := x]


Γ, x : A |- BK
-------------------------------------
Γ |- (x : A) -> B : K

--------------------
Γ |- M[Φ]N[Δ] : K

Γ |- M[0 :: Φ @ ↑]N[0 :: Δ @ ↑]
----------------------------------
Γ |- (x => M)[Φ](x => N)[Δ]

2[Δ @ ↑] == 2[Δ @ ↑]


Γ |- 1[Δ] == 1[Δ]
------------------------------------------
Γ |- (x => 1)[1 :: Δ] == (x => 2)[Δ]


Γ |- 2[0 :: 1[] :: M[] :: Δ @ ↑] == 2[0 :: N[] :: Δ @ ↑]
----------------------------------------------
Γ |- (x => 1)[Φ] == (x => 2)[Δ]


(M[K]) N
(M[K]) N
(M N)[K]

(M[K]) 0

(M[K] 0)
(0 _K)

(M[K] 0)

L<(λx. M) N> |-> L<M[x := N]>

M[][0][K]


(x = K; f x) N

(λ0)[K] N
(λ0) N
N

(λ0 1)[K] N
(λ0 K[]) N
N K


((λ0 1) 0)[K]
((λ0 1) 0)[K]
((λ0 K) K)
(K K)


0[0[K]

(x => 1)[1][3]


(x => y => M) "A" "B"


(x, y) = ("A", "B");
M[x := "A"][y := "B"]

pair => (
  (x, y) = pair;
  x + y
);

pair => (x + y)[(x, y) = pair];

pair => (x + y)[x := (x, y) = pair; x][y := (x, y) = pair; y]
pair => (((x, y) = pair; x) + ((x, y) = pair; y))

(x : Nat) -> Nat == (x : String) -> Nat

(x => 1)[0][0]
(x => 1[0 :: 0])
(x => 1)[1] == (x => 2)[id]



(String |> Token[] |> Ctree |> Ltree |> Ttree) // syntax
(Ttree |> Ttree) // checking
(Ttree |> Utree -> Jtree -> String) // jsend

(Syntax |> Jsend) // syntax + jsend


Nat64 : Data;
i < n : Prop;

Socket : Resource;

Array : {
  get : <A, n>(arr : Array n A, i : Nat64 & i < n) -> A;
  make : <A>(length : Int64 & length >= 0, initial : A) -> Array length A;
} = _;

safe_div : (n : Int64, m : Int64 & m != 0) -> Int64;
unsafe_div : (n : Int64, m : Int64) -[Division_by_zero]> Int64;

(n : Nat64) => (arr : Array n Int64) =>

(n : Nat64, arr : Array n Int64)
Array 15 Int64

Degen De-bruijin

(λx. M) NM[N]
(λM) NM[N]

M[K] N(M N[])[K]

M[0 .] NM

(λ0 0[])[] N
(λ(0 0[])[0 :: ↑ @ ↑]) N
(λ(0 0[][])) N
(0 0[][])[N]
(λ0 (0[]))[] N
(0 2)[N]
(N 1)

(λ0 1)[] N
(0 1)[N . id]
(N[] 0)[]

(λ0 1)[][N[]][]
(N[] 0)[]

(λ0 1)[][][N]
(0 1)[N[]][]
(N[] 0)[]



(0 1)[][N]

(λ0 1)[][][N]
(λ0 2)[][N]
(0 2)[N]
(N 2)

(λ0 1)[][N[]][]
(0 1)[N[]][]
(N[] 1)[]
(N 2)


(M[] N)[K]M N[K]
((λ0)[] N)
((λ0) N)
((λ0) N)
((λt) v)[u]
- t[v][u] // beta
- t[⇑u][v]

(M[] N)
((λ0 1)[] N)
((λ0 2) N)
(N 1)

(M N)[]M[] N[]


M[][] == M[]

M[][N] == M

M[][0] == M
M[][N] == M[]

M[] == M[][0][]

0[][0] |-> 1 |-> 0
1[][0] |-> 2[0] |-> 1
2[][0] |-> 3[0] |-> 2

n[](1 + n)
(1 + n)[] ≡ n

M[] N(M N[])[K]
(λM)[]


(λ0 1)[]
(λ0 2)

(λ(0 1)[][0])

(1[] N[])[]

(1 N[])[]

(0[]) 0(0 0[])[]

M[S] N(M N[-S])[S]


((λt) v)[u]
- t[v][u] // beta
- t[⇑u][v]

(1 0)[v][u]
(0 v)
u v

(u v)
(λ0 1)[K] N
(λ(0 1)[K]) N
(0 1)[K][N]
(0 K)[N]
N K

(λ0 1)[K] N
(0 1)[N[]][K]
(N[] 0)[K]
(N[][K] 0)
(N[K] 0)

(λM) N |-> M[K][N]



(x => M) N |-> M[x := N] // beta
M[x := K] N |-> (M N)[x := K] // extract
C<x>[x := N] |-> C<N>[x := N] // ls


M[x := N] |-> M  x ∉ fv(M) // gc

(λM) N |-> M[N] // beta

0[N]N
M[][N]M

(M N)[K]M[K] N[K]

M[K] N(M N[])[K]
(M[] N)[K]M N[K]

(λλM[]) K
(λM[])[K]
λM[K][]

(λλ(0 0[])) K
(λ(0 0[]))[K]

λ(M N[])[K]

(λ(M N[])) == λ(0[] N)[]

(λ(0 0[])) == _ (λ0[])


(λλ(0 (0[] )))

λ(0 ((λ0 0) (λ0[])))

(λ(0 0[]))[λ0[]]
λ(0[])

λ(M N)(λM) (λN)
(λM) (λN)

(0 0[])[K]
(0 0[])[][K]
λ(0[] K)[]
λ(0 K[])

(λ(0 1)[])[K]

(λ(0 0[]))[K]

M[K][0]

0 :: (_ 0)[S]
0 :: (S 0)[S]
(M N)[S]M[S] N[S]

(M N)[0] |-> (M[n ↑] N[n ↑])
(λM)[n ↑] |-> λM[(1 + n)]
n[m ↑]  n < m |-> n
n[m ↑]  n >= m |-> 1 + n


((y => t)[x := u] v)
((y => t) v)[x := u]
t[y := v][x := u]



M[x := K] N(M N)[x := K] // extract
M[K] N(M N[])[K] // using de-bruijin

(x => y => M) N K
(y => M)[x := N] K
((y => M) K)[x := N]
M[y := K][x := N] // names are preserved in order
// so
((x => y => M) N K)(x = N; y = K; M)


------------------
(x : Nat) & String

(x : String) & Nat


Γ |- S <: A  Γ, x : A |- S <: B
-------------------------------
Γ |- S <: (x : A) & B


(M[K] N)(M N[])[K]



0[N]N
M[][N]M

(M N)[K]M[K] N[K]

// theorems
M[K] N(M N[])[K]
(M[] N)[K]M N[K]

M[] N ≡

----------------------
M[]

Term ::= n | λM | M N | M[N];

(0)[N][Γ] |-> N
(1 + n)[N][Γ] |-> n[Γ]
((λM)[Δ] N)[Γ] |-> M[N[Γ]][Δ][Γ]

(λM)[Γ](λM[0][Γ])[_]
(λ0 1)[N]

λ0[0][N] 1[0][N]
λ0 N[]

M[0][Γ]N[0][Δ]
-------------------------------------
(λM)[Γ](λN)[Δ]

(M[K] : A)

M N |-> M[apply N]
(λM)[Δ][apply N] |-> M[N][Δ]

P 1 := _B[N]

(P 1)[][N] == _B[N]
(P 1)[] == _B
(P 1)[N] == _B[]

b
| true => (x : P true)
| false => (x : P false)

b (_ : true == true) _ : b == b

---------------
M NB[x := N]


ind b _ _ : b == b

b == b == _B b
b == b == (λx. _M) b
b == b == _M[x := b]
(b == b)[b := x][x := b] == _M[x := b]
(x == x) == _M
b == b == _B b
_B := λ_M
b == b == (λ_M) b
b == b == _M[b]

_B := λ_M

n == n == (λ_M) n
n == n == _M[n]

(n == n) == _M[n]
(2 == 2) == _M[2]

(2 == 2)[0][1][2]

3 == 2 == (λ_M) 2
3 == 2 == (λ_M) 2

(λλλλ(3 == 2)) 3 2 1 0
(3 == 2)[0][1][2][3]
(1 == 0)[2][3] == _M[2]
(4 == 0)[2] == _M[2] // how

(λλλλ(3 == 2)) 4 2 1 0
(3 == 2)[0][1][2][3]
(3 == 2)[0][1][1][4][2]
(1 == 0)[1][4][2]
(0 == 1)[4][2]
(4 == 0)[2]

(4 == 0) == _M
(3 == 2)[2][3]


(1 == 0)[2][3] == _M[2]

(3 == 2)[0][1][2] == _M[2]
(1 == 0) == _M
(λ(1 == 0)) n
(λλλ(2 == 2)) 2 1 0 == _M[2]
(2 == 2)[0][1][2] == _M[2]
(2 == 2)[0][1] == _M
(0 == 0) == _M
(λλ(2 == 2)[0]) 1 2 == _M[2]

_M := (b == b)[]



b (_ : true == true) _ : b == b

_P true ≡ true == true

_P true ≡ true == true

(P true)

[N]|- (P 1)[] == _B

M[apply N :: Δ]
M[apply N][Δ]
C<0[N][Γ]> |-> C<N>
C<(1 + n)[N][Γ]> |-> C<n[Γ]>

(λM)[Γ] |-> λM[Γ]

(λ(0 1))[M][Γ]
λ(0 1)[0][M][Γ]
L<λM> N |-> L<M[N; |L|]>

M N


--------------------
Γ, x : A |- 0A[]
M[N] |-> M{N}

(λλ0 1)[k] N

(λ0 1)[0 := N]
(λ0[0 := N] 1[1 := N])
(λ0 1[1 := N])
(λ0)[] ≡ λ0


M[x := K] N(M N)[x := K]
M[] NM[K] N(M N)[x := K]

L<M>


------------------------
Γ, x : A |- M[] == N[_]



M NM[split][N] // beta
(λM)[split]M[K] N(M N[])[K]
(M[] N)[K]M N[K]

(x => M) N |-> M[x := N] // beta
M[x := K] N |-> (M N)[x := K] // extract

Env + Context

Term ::= n | λM | M N | M[N] | M[] | M[Γ];
Env (Γ, Δ) ::= • | N :: Γ | Γ[];

M[N][Γ] |-> M[N :: Γ]
M[][Γ] |-> M[:: Γ]

0[N :: Γ] |-> N
(1 + n)[N :: Γ] |-> n[Γ][]

n[Γ] |-> (1 + n)[Γ]

(λM)[Γ] |-> λM[0 :: Γ[]]

----------------------
Γ, x : A |- x\0 : A[]

M[K] N(M N[])[K]
(M[] N)[K]M N[K]


M N |-> M[apply][N]
(λM)[apply] |-> M

M[K][apply][N]M[apply][N[]][K]
M[][apply][N]M[apply][][N]


0[N :: S] |-> N
(1 + n)[N :: S] |-> n[S][]


M[N][Γ] |-> M[N[Γ] :: Γ]

(M[])[N :: S] |-> M[S][]
M[][N] |-> M


(1 2)[0 :: 1 :: 1 :: 1]

(M N)[]
(λM)[] ≡ λM[0 :: 1]

0[N :: S] |-> N
(1 + n)[N :: S] |-> N

(0 1)
(λ0 1)[] ≡ λ0 2

(λ(0 1))[1]λ(0 1)[0 :: 1]
(λ(0 1))[0]
0 N |-> 0[apply]


Term ::= 0 | M[] | M[N] | λM | M N;
Env (Γ, Δ) ::= • | N :: Γ | Γ[];

M[↑ @ Γ] |-> M[Γ]{}



0[N :: Γ]N
M[][N :: Γ] |-> M[Γ]
M[N][Γ]M[N :: Γ]
M[][N]M

(λM) NM[N]
M[K] N(M N[])[K]
(M[] N)[K]M N[K]

M[N][Γ]M[N :: Γ]

(M[K] N)[Γ] |-> (M N[])[K :: Γ]

(λM)[Γ] |-> λM[0 :: Γ[]]

(M[] N)[Γ] |-> (M N[])[Γ[]]

0[N :: Γ] |-> N
0[]

()
M N |-> M[apply][N]
(λM)[apply] |-> M


M[N][Γ] |-> M[N :: Γ]
M[][Γ] |-> M[:: Γ]



f(x) = f(x)     f is injective
x = x
g(x) = g(x)


Term (M, N) ::= x | x => M | M N | M[x := N];

(x => M)L N |-> M[x := N]L // db
M[x := N] |-> M{x := N} // s

Term (M, N) ::= x | x => M | M N | M[x := N];

(x => M) N |-> M[x := N] // beta
M[x := N] |-> M{x := N} // s
M[x := K] N(M N)[x := K]  x ∉ fv(N) // move

Term (M, N) ::= n | λM | M N | M[N] | M[];

(λM) N |-> M[N] // beta
M[N] |-> M{N} // subst
M[] |-> M{} // shift

M[K] N(M N[])[K] // move

Term (M, N) ::= n | λM | M N | M[Γ];
Env (Γ) ::= • | ↑ :: Γ | N :: Γ;

(λM) N |-> M[N] // beta
M[Γ] |-> M{Γ} // shift+subst

M[K] N(M N[])[K]
M[K][Γ]M[K :: Γ]
M[][Γ]M[:: Γ]

Term (M, N) ::= n | λM | M N | M[Γ];
Env (Γ) ::= • | ↑ :: Γ | N :: Γ | Γ @ ↑;

(λM) N |-> M[N] // beta
M[Γ] |-> M{Γ} // comp-shift+subst

(λM)[Γ] ≡ λM[0 :: Γ @ ↑]
M[K] N(M N[])[K]
M[K][Γ]M[K[Γ] :: Γ]
M[][Γ]M[:: Γ]

Term (M, N) ::= n | λM | M N | M[Γ];
Env (Γ) ::= • | ↑ :: Γ | N :: Γ | Γ @ ↑;

(λM) N |-> M[N] // beta
M[Γ] |-> M{Γ} // comp-shift+subst

(λM)[Γ] ≡ λM[0 :: Γ @ ↑]
M[K] N(M N[])[K]
M[K][Γ]M[K[Γ] :: Γ]
M[][N]M


Term (M, N) ::= n | λM | M N | M[N];

L<λM> N |-> L<M[N]>
C<0>[N] |-> C<N{}>[N] // ls
M[N] |-> M{\downarr}  0fv(M) // gc


(λC)<N> |-> λC<N[]>

Term (M, N, K) ::= n | λM | M N | M[Γ];
Env (Γ) ::= • | ↑ :: Γ | K :: Γ | Γ @ ↑;

(λM) N |-> M[N] // beta
M[Γ] |-> M{Γ} // comp-shift+subst

(λM)[Γ] ≡ λM[0 :: Γ @ ↑]
M[K ::] N(M N[])[K]
M[K ::][Γ]M[K[Γ] :: Γ]
M[::][Γ]M[:: Γ]


(:: K :: Γ) ≡ Γ

↑ @ Γ, 0 |- MN
-----------------
Γ |- λM ≡ λN


Term (M, N, K) ::= n | λM | M N | M[Γ];
Env (Γ) ::= • | ↑ :: Γ | K :: Γ | Γ @ ↑;

M[0 :: Γ @ ↑]N[0 :: Δ @ ↑]
-----------------------------
(λM)[Γ](λN)[Δ]


_M[0][K] ≡ _N[1][K]
_M[0] ≡ _N[1]
_M[K :: 0] ≡ _N[K :: 1]

M[K :: 0] ≡ _N[K :: 1]

M[][K :: 0]
M[][K :: 0]
M[][K :: 0]

_M[K :: 0] ≡ _N[K :: 1]

_M[0][K] ≡ _N[1]

0[0 :: 2]0[1 :: 2]
_M[0] ≡ _N[1]

-----------
M[Φ]N[Δ]

-------------
• |- M[]N

0[][]
0[]
x => x
λ0

x => y => x
λλ1

x => y => y
λλ0

MN
-------
λM ≡ λN



(x => M)(N) |-> M{x := N}

(x => x + x)(1) |-> (x + x){x := 1} |-> (1 + 1) |-> 2

Term ::= n | λM | M N;

(λM) N |-> M{N} // beta

Term ::= n | λM | M N | M[N];

(λM) N |-> M[N] // beta
M[N] |-> M{N} // subst

Term ::= n | λM | M N | M[N];

(λM) N |-> M[N] // beta
M[K] N |-> (M N{})[K] // move
M[N] |-> M{N} // subst

M[x := K] N |-> (M N)[x := K]
(x => M)[y := N] |-> x => M[y := N]
M[x := N][y := K] |-> M[y := K][x := N]

(M[K] N)
(M{K} N)
(M N{})[K]
(x = K; y => M) N
(x = K; y => M) N
x = K; (y => M) N // move
(x = K; y = N; M)


Term (M, N, K) ::= n | λM | M N | M[Γ];
Env (Γ, Δ) ::= • | K :: Γ;

0[K :: Γ] |-> K
(1 + n)[K :: Γ] |-> n[Γ]{}

(λM)[Γ] |-> λM[0 :: Γ{}]
M[K][Γ] |-> M[K[Γ] :: Γ]

Term (M, N, K) ::= n | λM | M N | M[K];

(λM) N |-> M[N]
M[K] |-> M{K}


M[x := K] N |-> (M N)[x := K]

_M[K] N
(_M N)[K] // _M = λ_M2
(λ_M2 N)[K] // eta
_M2[N][K]

(_M N)

(λ((λ0) K) 0) N
  (λK 0) N
  ((λ0) K) N

(λ0[K] 0) N
  (0[K] 0)[N] // beta
  (λK 0) N // s

(M[x := K] N)[x := K] -(s)> M[x := K] N  x ∉ N
(M[x := x] N)[x := K] -(s)> M[x := K] N  x ∉ N

(M N[x := K])[x := K] -(s)> M N[x := K]  x ∉ M

M[x := K] N(M[x := K] N)[x := K]  x ∉ N  x ∉ K

(f = x => M; f) N |->

(f = x => M; f N) |->


Term (M, N, K) ::= 0 | λM | M N | M[K] | M[];

(λM) N |-> M[N]
M[K] N |-> (M N[])[K]


(M[] N)[K] |-> M N

0[K[Δ] :: Γ] |-> K[\Del]
(1 + n)[K :: Γ] |-> n[Γ][]

n[:: Γ] |-> (1 + n)[Γ]

(λM)[Γ]

0[][K :: N :: _]
0[][K :: N :: _]
0[][K][N]

0[:: K :: N]
1[K :: N]


Term (M, N, K) ::= n | λM | M N | M[K];

(λM) N |-> M[N] // beta
M[K] N |-> (M N{})[N] // move
M[K] |-> M{K} // subst



Term (M, N, K) ::= n | λM | M N | M[K] | M[];


------------------------------
0 | S | N :: E |-> N :: C | E

λM :: S | EM :: λ_ :: S | 0 :: E
M N :: S | EM :: _ N :: S | E
M N :: S | EN :: M _ :: S | E

M N |  | E |-> M | _ N :: S | E

M | _ N :: S | E |->

----------------
M N

(λM) N |-> M[N] // beta
M[K] N |-> (M N[])[N] // move
M[K] |-> M{K} // subst

(λM) N :: Γ |-> M{N} :: Γ // beta
(λM) N :: Γ |-> M{N} :: Γ // beta

-----------------
0 | Γ |  |->

-----------------
0 | Γ |  |->

------------------------
λM :: Γ |-> M :: λ_ :: Γ

M |-> λK
--------------
M N |-> λK

C<(λM) N> |-> M[N] // beta


(λ((λ0) K) 0) N
  ((λ0) K) N // beta
  (λK 0) N // beta

(M[K] N) |-> M_K N // subst
(M[K] N) |-> (M N{})[K] // move

(M N{})[K] |-> M_K N // subst


Term (M, N, K) ::= n | λM | M N | M[K] | M[];

M[K] N(M N)[K]  if ∅ ≡ fv(N)
M[] N(M N)[]  if ∅ ≡ fv(N)

M[K] N(M N[])[K]

M[] N(M N[])[1 ::]

(M[] 0)(M N[])[0]

M[] N(M N[])[]


Term (M, N, K) ::= n | λM | M N | M[K] | M[] | M[_];

0[K] |-> K
(1 + n)[K] |-> n[K][]

M[K] N |-> (M N[])[K]
M[] N |-> (M N[])[_]
M[_] N |-> (M N[])[_]

M[_][K] |-> M[K]
M[][K] |-> M

M[K] |-> M{K}
M[] |-> M{}




(M[] N)

(M[] N) |-> (M N[])[_]

(0[] N)[T][U] |-> (U N[T][U])

(0[] N)[_]

M[_][T]
M[T]

(0[] N[])[_K]
(0[] N)
(0[][] N[])[_K]
(0 N[])[_K]

M[] N |-> (M N[])[_K]

(M N[])[0 / _K][0 / U]

M[] N |->

M[K] N(M N[])[K]
(M[] N)[K]M N[K]

(M[] N)(M N[])[_U]

(M[] N)[K]M N[K]


(M[] N)[_U]M N[_U]

(M[] N)[K]

M[_A]M[K]
_A ≡ K


((x = K; M) N) |-> (x = K; M N) // preserves
(M (x = K; N)) |-> (x = K; M N) // shrunken
(x = (y = K; N); M) |-> (y = K; x = N; M)

Term (M, N, K) ::= n | λM | M N | M[Γ];

0[N :: Γ] |-> N
(1 + n)[N :: Γ] |-> n[Γ][]

(λM)[Γ] |-> λM[0 :: Γ]
(λM)[Δ] N |-> M[N :: Δ]

M N



M[x := N][y := K]
M[y := K][x := N]

M[x := z][y := K][z := N]


M[0 :: 0 :: Δ][N][K] |-> M[N :: Δ]

M[0 :: 0 :: Δ][N :: K] |-> M[0 :: 0 :: Δ @ N :: K]

M[0 :: 0 :: Δ @ N :: K]

(N :: Δ @ K :: Γ)(N[K] :: Δ @ Γ)

0[0 :: 0 :: Δ][N][K]
N[K]

1[0 :: 0 :: Δ][N][K]
K

0[0 :: 0 :: Δ][N :: K]
N

1[0 :: 0 :: Δ][N :: K]
K

M[0 :: Δ] |->
M[0 :: Δ]


M[N][Γ] |-> M[N[Γ] :: Γ]


(λM)[Γ] |-> λM[0 :: Γ]


(λM)[0 :: Δ] N |-> M[N :: Δ]


Term (M, N, K) ::= n | λM | M N | M[Γ];
Context (Γ) ::= _ | ↑n | N :: Γ;

0[N :: Γ] |-> N
(1 + n)[N :: Γ] |-> n[Γ][]

(λM)[Γ] |-> λM[0 :: Γ]
(λM)[Δ] N |-> M[N :: Δ] // db



(x => M) N |-> N[x := M]
N[x := M] |-> (x => M) N
(x => M) NN[x := M]

Term (M, N, K) ::= n | λM | M N;
Env (Δ, Φ) ::= K :: Δ | ↑ :: Δ;

(λ0 1)[] N |-> (0 2)[N] |-> N 1

(λ0 1)[] N |-> (0 1)[N ::]

((λ0 1)[] N)[K] |-> (λ0 1) N[K] |-> (0 1)[N[K]] |-> N[K] 1

(λ0 1)[][] N |-> (0 3)[N] |-> N 2

(λ0 1)[][] N |-> (0 1)[N :: ↑↑]

(λ0 1)[K][] N |-> K[][N]

(λ0 1)[K][] N |-> (0 3)[N] |-> N 2

0[N ::] 1[N ::]

(λM)[] N |-> M[N][]

(λ0 1)[] N |-> (0 1)[N][]

(M[] N)[K] |-> M N[K]

M N |-> (M N)[]

(λM) N |-> M[N] // beta
M[N] |-> M{N} // subst


f x ((x => M) N)


Term (M, N, K) ::= n | λM | M N | M[Δ | s];
Env (Δ, Φ) ::= • | N :: Δ;

M[• | s] |-> M

0[N | s] |-> N[• | s]
(1 + n)[N :: Δ | s] |-> n[Δ | 1 + s]

(λM)[Δ | s] |-> λM[0 :: Δ | s]
(λM)[Δ | s] N |-> M[N :: Δ | s]
(M N)[Δ | s] |-> M[Δ | s] N[Δ | s]

M[][K :: Δ | s] |-> M[Δ | 1 + s]

Γ |- M[N :: Φ]K[Δ]
-----------------------
Γ |- ((λM) N)[Φ]K[Δ]

Γ |- M[0 :: Φ]N[0 :: Δ]
--------------------------
Γ |- (λM)[Φ](λN)[Δ]

N[0 :: Δ][Γ]
N[Δ][0 :: Γ]

Γ, 0 |- MN[0 :: Δ]
---------------------
Γ |- λM ≡ (λN)[Δ]


Γ |- M[]M
-----------------
Γ |- (λM)[] ≡ λM

(M[] )[K]
(λ0 1)[] N |-> (0 1)[N ::]


Term (M, N, K) ::= n | λM | M N | M[Δ | s];


y : A;
x : A;
x = y;
y = x;
M


y : A;
x : A;
x = y;
y = x;
M


x : A;
y : A;
x = y;
y = x;

[0 / 0 : A];
[0 / 0 : A];
[0 / 1 : A];
[0 / 1 : A];
M



0[0 / 1][0 / 1]
1[0 / 1][0 / 1]

M[1][1][0][0]

M[1][0]

M[x := y][y := x]

M[1 :: 1]

M[0][2][2][3]
0[1 :: 0]

2[1 :: 2 :: 2 :: 3]
0[1 :: 1 :: 0 :: 0] |-> 1[1 :: 1 :: 0 :: 0]

1[1 :: 0] |-> 0[1 :: 0] |-> 1[1 :: 0]

1[1 :: 0] |-> 0[1 :: 0] |-> 1[1 :: 0]

1[Γ] |->

(λM)[Γ] |-> λM[0 :: Γ]

n[Γ] |-> n{Γ}[Γ]
0[K :: Γ] |-> K[|K| :: Γ]
(1 + n)[]
0[0 :: Γ] |-> 0[{0} :: Γ]
(λM)[Γ] |-> λM[0 :: Γ]
((λM)[Δ] N) |-> M[N[] :: Δ]


Term (M, N, K) ::= x | x => M | M N | M[x := N];

x[Γ] |-> x{Γ}[Γ]


Γ, x := z, y := z |- MN
--------------------------
Γ |- (x => M)(y => N)

Γ, x := z, y := z |- _A ≡ y
---------------------------
Γ |- (x => _A)(y => y)

Γ, x := z, y := z |- _A ≡ y
---------------------------
Γ |- (x => _A)(x => y)

Γ, x := z, y := z |- _A ≡ y
---------------------------
Γ |- (x => _A)(x => y)

Γ, x := z, y := z |- _A ≡ z[z := x]

Γ |- y => x == x => y
-----------------------------------
Γ |- (x => y => x) == (y => x => y)

Γ, y := a, x := a |-
---------------------
Γ |- y => x == x => y


x : A;
y : A;
x = y;
y = x;
M

x : A;
y : A;
x = y;
y = x;
M

M[0 / 1][1 / 0]
M[0 / 1][1 / 0]

M[1 :: 0]

(x : Nat) => (x == x + 1) => _

M[0 == N][1 == K]
M[0 == N][0 == K]

M[0 == N][2 == K]
M[0 == N | 1 == _ | 2 == K]
M[0 == N | 1 == K]
M[0 == 1][1 == 0][0][0]
M[0 == 1][1 == 0][0][0]

M[0 == 1][2 == 0]
M[0 == 1][1 == 0]

(λM)[0 == 1]
λM[↑ | 0 == 1]

M[0 == 1 | 2 == 0]
0[0 == 1][1 == 0][0][0]
1[0 == 1][1 == 0][0][0]

M[0][0][_][_]
M[0 :: 1 :: _][_]


x : Nat;
x = x + 1;

[_ : Nat]
[]

(x : Nat) => (x == x + 1) => _;

Γ |- (y => x) == (x => y)
-----------------------------------
Γ |- (x => y => x) == (y => x => y)


Term (M, N, K) ::= n | λM | M N;

x : A;
y : A;
y = x;
x = y;
M


n[Γ] |-> K[Δ]
-----------------------------------
(1 + n)[m == K][Γ] |-> K[m == K][Δ]

(λM)
(λM)[0 := 1][1 := 0]

M[0 / A][0 / B][0 / C]
M[0 / A :: 0 / B][0 / C]
(1 0)[0 / N][0 / K]
(1 0)[0 / N][0 / K]

x : A;
y : A;
y = x;
x = y;
M

(x : A) => (y : A) => (y == x) => (x == y) => _;

x : A;
y : A;
x = y;
y = x;
M

Term (M, N, K) ::= n | λM | M N | M[N; ...] | M[];
Env (Γ, Δ, Φ) ::= • | N :: Γ | Γ[↑ n] | Δ @ Γ[↑ n];


M[K][Γ] |-> M[K; Γ @ ↑]

M[Δ][Γ | n]

M[Δ][][Γ | n]

0[N :: _][][Γ | 0]
0[N :: _][Γ | 1]
N[][Γ | 0]
0[][Γ | 1]

0[][A :: B :: Γ]
1[A :: B :: Γ]
B[A :: B :: Γ]

0[][0 | A :: B :: Γ]
0[1 | A :: B :: Γ]
B[0 | A :: B :: Γ]


0[K][][0 | A :: B :: Γ]
0[K][1 | A :: B :: Γ]

0[N][K][A :: B :: Γ]
0[N][K][][A :: B :: Γ]
0[N][K][1 | A :: B :: Γ]

0[N][K][][A :: B :: Γ]
0[N[] :: K[] :: A :: B :: Γ]
N[N :: K[] :: A :: B :: Γ]

0[N][K][][A :: B :: Γ]
0[N][K][][A :: B :: Γ]

M[N][K][][Γ]
M[N][K][1 | Γ]
M[N][K][1 | K :: Γ]

M[N][K][Γ]
M[N][K :: Γ{}]
M[N :: K[] :: Γ{}]

N[K][]
0[N[] :: K[][] ::][]

K[][N][K][]
1[N[] :: K[][] ::][]

M[1][0]
M[N][K][0 | K :: Γ{}]
0[N][K][][Γ]
N[K][][Γ]
0[N][K][1 | Γ]
0[N][0 | K :: Γ{}]

0[0 | K[] :: A :: B :: Γ]
1[0 | K[] :: A :: B :: Γ]

0[K[]][][0 | A :: B :: Γ]

0[0 | (1 | K :: A :: B :: Γ)]
K[1 | K :: A :: B :: Γ]


M[N ::][][Γ | 0]
M[N ::][Γ | 1]
M[N :: Γ | 1]

M[Δ ][Γ] |-> M[Δ @ 0 | Γ]

n[Δ | d][Γ | g] |-> (n + d)[Δ][Γ | g]
N :: Δ[↑ n] @ n | Γ |-> Δ | n @ 1 + n | Γ
Δ | n @ Γ |->

• @ n | Γ |-> Γ @ ↑n

N :: Δ @ n | Γ |-> Δ @ 1 + n | Γ

M[][Γ | n] |-> M[Γ | 1 + n]

(eq : Nat == Bool) => not (eq _ 1)
(eq : Nat == Bool) => not 1

[eq] |- not 1

(eq : Nat == Bool) => not 1

(eq : Nat == Bool) => (not (1 : Bool))
(eq : Nat == Bool) => (not (1 : Bool))

M[0 := N; 1 := K]
0[A][0 := N; 1 := K]
0[0 := A; 1 := N[]; 2 := K[]]

(λM)[n := N] |-> λM[1 + n := N[]]
(λM[1 := N[]])

M[1 := N][Γ] |-> M[Γ + 1 := N]

m[Γ | n] |-> (m + n)[Γ]

m[][Γ | n] |-> m[][Γ | 1 + n]

1[1 := N][_ :: 1 :: Γ]

n[1 :: 0]
(x : Nat) => (x == )
(λM)[]


Term (M, N, K) ::= n | λM | M N | M[N; ...] | M[];
Env (Γ, Δ, Φ) ::= • | N :: Γ | Γ[↑ n] | Δ @ Γ[↑ n];


1[1 :: 0 :: Δ]

(x => M) N |-> M{x := N}

1[- 0 | 1 :: - 1 | 0 :: Δ]

1[- 0 | 1 :: - 1 | 0 :: Δ] |-> 0[- 0 | 1 :: - 1 | 0 :: Δ]

1[- 0 | 1 :: 0 | 0 :: Δ]


1[- 0 | 1 :: 0 | 0 :: Δ]


(M[] : A)[K]
(M[] N)

(M[] : A) |-> (M[] : A)

M[][n | A :: B :: Δ]
M[1 + n | A :: B :: Δ]

(M[] N)[0 | A :: B :: Δ]
(M N[])[1 | A :: B :: Δ]

(M[] N)[0 | A :: B :: Δ]

(M[] N)[K] |-> M N[K]


(M[] N)[0 | A :: B :: Δ]
(M[] N)[0 | A :: B :: Δ]
(M N[])[1 | A :: B :: Δ]

(M[] N)[1 | A :: B :: Δ]

Env ::= (n, N) :: (m, M) :: Δ


(M[] N)[0 | A :: B :: Δ]( N)[0 | A :: B :: Δ]

((λM)[] N)[0 | Γ]
((λM)[][0 | Γ] N[0 | Γ])
((λM)[1 | Γ] N[0 | Γ])
(λM[0 :: Γ{1}]) N[0 | Γ]

((λM)[] N)[n | Γ] |-> M[N :: _ :: ]

(λM)[][n | Γ] |-> M[N :: _ :: ]

((λM)[] N)[n | Γ] |-> M[N :: _ :: ]


M[][Γ] |-> M[A :: B :: Δ]
M[K][][Γ] |-> M[K[A][] :: B :: Δ]
M[][Γ] |-> M[A | B :: Δ]

M[][A :: B :: Γ] |-> M[A | B :: Δ]
0[][A :: B :: Γ] |-> 0[A | B :: Γ]

0[A | B :: Δ] |-> B[A :: B :: Δ]



M[K][A | B :: Γ] |-> M[K :: B :: Γ]
M[K][A | B :: Γ] |-> M[A | B :: Γ]
[][Γ] |-> M[A | Γ]


M[K][][A :: B :: Γ] |-> M[K :: B :: Γ]

M[K][][A :: B :: Γ] |-> M[K :: B :: Γ]

M[][A :: Γ] |-> M[A | Γ]
M[K][A | Γ] |-> M[K :: Γ]

M[K][1 | Γ] |->
M[K][1 | Γ] |-> M[K :: Γ{}]
M[K][][A :: B :: C :: Γ] |-> M[K :::: A :: B :: C :: Γ]

M[K][] |-> M[| K :: Γ]
M[K][A | B :: Γ] |-> M[A | Γ]


[A :: B :: C :: Γ]
[A; B :: C :: Γ]
M[][| A :: Γ] |-> M[A | Γ]
M[][| A :: Γ] |-> M[A | Γ]

M[K][n | A :: B :: Γ] |-> M[1 + n | A :: B :: Γ]

M[K][n | A :: B :: Γ] |-> M[1 + n | A :: B :: Γ]


x : A;
y : A;
x = y;
y = x;

Block ::= M; B | •
Env ::= M :: Γ | B :: Γ

M; N :: Γ

M[][N :: Γ] |-> M[Γ]
M[][A; Γ] |-> M[A | Γ]

M[][A :: Γ] |-> M[A | Γ]
M[K][A | Γ] |->

M[N][Γ] |-> M[N :: Γ]

0[N :: Γ] |-> N[Γ]

0[(N; B) :: Γ] |-> N[Γ]

0[Δ; N :: Γ] |-> N[Γ]
(1 + n)[Δ | N; B :: Γ] |-> N[Δ :: N | B :: Γ]

0[(0 1)[K] :: B :: Γ]
0[(0 1)[K] :: B :: Γ]
0[A :: B :: Γ]

M[K][N | B; Γ] |-> M[K :: N | B; Γ]

[0]

M[K][B[A]; Γ] |->
M[K][A | B; Γ] |->
M[K][A | B; Γ] |-> M[K :: B; Γ]

M[][|(N; B); Γ] |-> M[N ::; B; Γ]
M[K][Δ | Γ] |-> M[Δ; K :: B; Γ]
M[][Δ; K :: B; Γ]
M[K][A :: • | B; Γ] |-> M[K :: B; Γ]
M[K][A | B; Γ] |-> M[K[0 := A] :: B; Γ]

0[A :: B :: Γ]
A[A :: B :: Γ]
[0 := 1][1 := 0][0, 0 :: 0, 0]
x =>
(x == N) =>
(x == M) =>

U = (A : Data, (A = A, A -> ()) -> ());
V = (A = U, A -> ());

Data (1 + _r) : Data (0 + _r)
Data (1 + 0 + _r) : Data (0 + _l)
_l := 1 + _r

U : Data 1 = (A : Data 0, (A = A, A -> ()) -> ());
V = (A = U, A -> ());

U : Data = (A : Data, (A = A, A -> ()) -> ());

(A = U, A -> ()) <: U


(A = U, A -> ()) <: U
(A = U, A -> ()) <: (A : Data 0, (A = A, A -> ()) -> ())
(A = U, A -> ()) <: (A : Data (0 + _l), (A = A, A -> ()) -> ())
(A = _r⇑U, A -> ()) <: (A : Data (0 + _l), (A = A, A -> ()) -> ())
(A = _r⇑U, A -> ()) <: (A = _r⇑U, (A = A, A -> ()) -> ())
_l := 1 + _r

(A = _r⇑U, A -> ()) <: (A = _r⇑U, (A = A, A -> ()) -> ())
(A = _r⇑U, A -> ()) <: (A : Data (0 + _r), (A = A, A -> ()) -> ())


n⇑M : Data l |-> Data (l + n)

(A = _r⇑U, A -> ()) <: (A = _r⇑U, (A = A, A -> ()) -> ())

(A = U, A -> ()) <: (A : Data (0 + _l), (A = A, A -> ()) -> ())

(A = U, A -> ()) <: U
(A = U, A -> ()) <: (A : Data (0 + _l), (A = A, A -> ()) -> ())

(A = _r⇑U, A -> ()) <: _e⇑U
(A = U, A -> ()) <: (A : Data (0 + _l), (A = A, A -> ()) -> ())
_l := 1 + _r
(A = _r⇑U, A -> ()) <: (A = _r⇑U, (A = A, A -> ()) -> ())
(A = _r⇑U, A -> ()) (A : Data (0 + _r), (A = A, A -> ()) -> ())

(A = U, A -> ()) -> U

(A : Data (0 + _l), (A = A, A -> ()) -> ()) <:=
(A = U, A -> ()) <: (A = U, (A = A, A -> ()) -> ())
(A = U, A -> ()) <: U

(A = U, A -> ()) <: (A = U, (A = A, A -> ()) -> ())
(A = U, A -> ()) <: (A = U, (A = A, A -> ()) -> ())
(A = U, A -> ()) <: U
V


----------------------------
(A : Data 1, x : A) : Data 1


(A : Data 0, x : A)

(A = U, A -> ()) <: U
(A = U, A -> ()) <: (A : Data 0, (A = A, A -> ()) -> ())

<r>(A = U<r>, A -> ()) <: U<e>
(A = U<_r>, A -> ()) <: (A : Data e, (A = A, A -> ()) -> ())
(A = U<_r>, A -> ()) <: (A : Data e, (A = A, A -> ()) -> ())

(A = U<e>, A -> ()) <: (A = U<e>, (A = A, A -> ()) -> ())


(A = U, A -> ()) <: U
(A = U, A -> ()) <: (A : Data : Univ, (A = A, A -> ()) -> ())
(A = U, A -> ()) <: (A : Data, (A = A, A -> ()) -> ())

A = U

(A = _r⇑U, A -> ()) <: (A : Data (0 + _e), (A = A, A -> ()) -> ())


x : Nat;
eq : x == 1;

x = 1;
eq = refl;

M[0 :: 0]

M[][A :: B :: Γ]
M[][A | B :: Γ]

M[K :: A :: B :: Γ]

0[K :: A :: B :: Γ]
K[K :: A :: B :: Γ]

M[K][A | B :: Γ]
M[A | K :: B :: Γ]

0[]


(x => M)

(x => x + x)
(fn x => x + x)

(x => y => x + y)

[] | (λ.λ. \2 + \1) 15 13
15 :: [] | (λ. \2 + \1) 13
13 :: 15 :: [] | \2 + \1
13 :: 15 :: [] | 15 + 13
13 :: 15 :: [] | 28
[] | 28

2 | [15; 13; M] | \2 + \1


[15; 13; M]

[15; [N; 13]; M]

[15; [N; 13]; M]
read (sp - i)
read (2 - 1)


print : (msg : String) -[IO]> ();

map : <A, B>(l : List A, f : (x : A) -> B) -[Alloc (length l)]> List B;

((x : Int) => (1 : Nat)) <: ((x : Nat) => (1 : Int))

((x :))



-------------------
Γ |- \0[Φ] == \0[Δ]


-------------------
(x => M)(y => N)


(
  Nat : Data;
  Nat = <A>(zero : A, succ : (pred : Nat) -> A) -> A;
  Nat
) = (
  Nat : Data;
  Nat = <A>(zero : A, succ : (pred : Nat) -> A) -> A;
  <A>(zero : A, succ : (pred : Nat) -> A) -> A
)

(A : +Type) -> (P : (z : A) -> Type) -> (x : P x) -> P y

(x => x x) (x => x x)

Type : Type
Data : Type
Prop : Type


(M[K] N) |-> (M N[])[K]
(M[] N)[K] |-> M N[K]((f x) y)(f z)


Id = <A>(x : A) -> A;
f : (id : Id) -> Id = _;
x = f; // Id -> Id, no binder



(x => M N) K
((x : A : Type) => (M : B : Type) (N : C : Type)) (K : D : Type)

(1 : String : Type 0)
(Type 0)

(A : Type 0) =>
(String : Type 0)


A = @self(x). T

A : Type;
A = (x : A) & T;


((x : Id A) : A) = _;


map : ;
map = (l, f) => l | [] => [] | el :: tl => f(el) :: map(tl, f);


Id : [l] -> Type (1 + l) =
  [l] => (A : Type l) -> (x : A) -> x;


id = (A : Prop) => (x : A) => x;

Type : Type

/M\
\M/
/M/
\M\

^

#macros
%macros
@

x%/* 1 */

Symbols

33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / 58 : 59 ; 60 < 61 = 62 > 63 ? 64 @ 91 [ 92
93 ] 94 ^ 95 _ 96 ` 123 { 124 | 125 } 126 ~

Symbol Table

32
46 .

33 ! 63 ?

64 @ 35 # 36 $

40 ( 60 < 91 [ 123 { 41 ) 62 > 93 ] 125 }

34 " 39 ' 124 |

42 * 43 + 45 - 47 /

37 % 94 ^

58 : 59 ; 61 =

38 & 44 ,

92 \

95 _ 96 `

126 ~

Typed Tree

#(M : A)
M#[x := N]
M#[l]
#Type

x#1
(M : A)

M # match # N

#print

f # a
f # a
(f #) a

x#1

(a #1)
f a # 1
f a # 1

(f a)#1

x (#1)

f # debug
(f #) debug
f (# debug)

#print "Hello"

concat #"Hello" "World"

#\"Hello"

∀A. (x : A) -> A

#forall A. ((x : A) -> A)
#"Hello" = 1;
f #A

M = [%graphql {
  users(id: 0) {
    name
    email
  }
}];

M = [%graphql { users (id : 0) { name email } }];

f = [%c {
  x: for (i = 0; i <= 10; i++) {
    print(i);
  };

  if (true) {
    print("a");
  } else {
    print("b");
  };

  goto x;
}];

#debug "Hello World"

(A : Type) => (x : A) => _


ind : <P : (b : Bool) -> Type>(b : Bool, then : P true, else : P false) -> P b;

Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : (u : Unit) -> Type) -> (x : P unit) -> P u;
unit = P => x => x;

Bool : Type;
true : Bool;
false : Bool

Bool = (b : Bool) & (P : (b : Bool) -> Type) ->
  (x : P true) -> (y : P false) -> P b;
true = P => x => y => x;
false = P => x => y => y;

ind (b : Bool)
  : (P : (b : Bool) -> Type) -> (x : P true) -> (y : P false) -> P b
  = b
Unit : Type;
unit : Unit;

Unit = (u : Unit) & (P : (u : Unit) -> Type) -> (x : P unit) -> P u;
unit = P => x => x;

Unit : Type = <A : Type>(x : A) -> A;
unit : Unit = x => x;


(x : A) & B

(x : Int) -> Int
(x : String) -> String


unit : ((x : Int) -> Int) & ((x : String) -> String) = x => x

f = (x : ((x : Int) -> Int) & ((x : String) -> String)) => _;

Teej

Id = <A>(x : A) -> A;
id : Id = x => x;

x : String = id "a";

id = (A : Data) => (x : A) => x;
x = id String;

Id = (A : Data) => A;
x : Id String = "Hello";


refl : <A>(x : A) -> x == x = _;
add = (a, b) => a + b;

_ : add (1, 2) == 3 = refl _;

Array : {
  create : <A>(length : Int & length >= 0, initial : A) -> Array<A>;
} = _;

_ = (length : Int & (length >= 0) : Prop);

f = (length : Int) =>
  length >= 0
  | true => create
  | false => _


(u : (A : Type#1) -> A#3) =>
  (u : (A : Type#1) -> A#4)


[Type; String; u] + 0; [Type; String; u] + 0 |-
  (A : Type#1) -> A#4((A : Type#1) -> A#3)#2
 + 0; [Type; String; u] + 0 |-
  (A : Type#1) -> A#4((A : Type#1) -> A#3)#2


[Type; String; u];

[Type; String; u] + 0 | [Type; String; u] + 0 |-
  (A : Type#1) -> A#4((A : Type#1) -> A#3)#2
[Type; String; u] + 0 | [Type; String] + 1 |-
  (A : Type#1) -> A#4(A : Type#1) -> A#3
[Type; String; u; A] + 0 | [Type; String; A + 1] + 1 |-
  A#4A#3 // works


(A : Type : Meta)

((M : A : Data) : (A : Meta))
(1 : Meta)


((x : _a) => x + 1)
((x : int) => x + 1)

_A : Type <: Int

_A ≡ Int

_A := [Int]

_A ≡ String

_A := [Int; String]

_A := Int & String


P (not b) ≡ _F b
P (not b)(x => _M) b
P (not b) ≡ _M[x := b]
(P (not b))[b := x] ≡ _M[x := b][b := x]
(P (not b))[b := x] ≡ _M
_M := P (not x)

_F := x => _M

P (not b)(x => P (not x)) b
P (not b)P (not b)


STLC + Option + Int + String + List

(id : 'A. 'A -> 'A : Type 2)


(f : _B -> _) => f id
('K <: 'A. 'A -> 'A). (f : 'K -> _) => f id

'B. (f : ('B -> 'B) -> _) => f id

_A : Type 0

_A :=


   |--|
λ. λ.-1

|-----|
λ. λ.-2

   |--|
λ. λ.+1
|-----|
λ. λ.+0

Int#+1 -> ((A : Type) -> A#-1) -> ()

λA. λ(x : A#1 -> A#1). (x : A#2 -> A#2)
λA. λ(x : (A. A#2)). (x : (A. A#3))

5
id = (M : _A#6 -> _A#6);
id = (M : 'A. 'A -> 'A);

id = (M : 'A#-1 -> 'A#-1);

Mono (τ) := σ -> τ | A#+l
Poly (σ) := τ | ∀. σ

Term =
  | T_arrow
  | T_var of { level : int }

Type = { mutable desc : Desc; mutable level : int }
Desc =
  | T_arrow
  | T_var
  | T_link of { to_ : Type }

Type = { mutable desc : Desc;  }
Desc =
  | T_arrow of { param : Type; return : Type; }
  | T_link of { to_ : Type }
  | T_free_var of { mutable binder : int }
  | T_bound_var of { mutable binder : int }. A#-1 -> B#-1 -> B#-1. A#g -> B#g -> B#g



∀. (. A#-1 -> B#-2) -> B#-1. (. A#0#-1 -> B#1#-2) -> B#1#-1

(. A#0#-1 -> _B#1) -> _B#1

(x => M)((x : Int) -> Int)

((x : Int) => (M : Int))(x : Int) -> Int

_A := _A -> _A



gen (_A -> _A)
gen 4 (_A#+5 -> _A#+5)
gen (_A#G -> _A#G). (. A#-2 -> B#-1) -> A#-


T =
  | (x : Int, tag == true, y : Int)
  | (x : Int, tag == false);


[Type; String; u] + 0 | [Type; String; u] + 0 |-
  (A : Type#1) -> A#4((A : Type#1) -> A#3)#2
[Type; String; u] + 0 | [Type; String] + 1 |-
  (A : Type#1) -> A#4(A : Type#1) -> A#3
[Type; String; u; A] + 0 | [Type; String; A + 1] + 1 |-
  A#4A#3

[Type; String; u] + 0 | [Type; String; u] + 0 |-
  (A : Type#1) -> x = A#4; x#5(A : Type#1) -> (x = A#3; x#4)#2

[Type; String; u] + 0 | [Type; String; u] + 0 |-
  (A : Type#1) -> (x = A#4 Type#1; x#5)((A : Type#1) -> (x = A#3 Type#1; x#4))#2
[Type; String; u] + 0 | [Type; String] + 1 |-
  (A : Type#1) -> x = A#4; x#5(A : Type#1) -> x = A#3; x#4
[Type; String; u; A] + 0 | [Type; String; A + 1] + 1 |-
  x = A#4 Type#1; x#5 ≡ x = A#3 Type#1; x#4
[Type; String; u; A; x == A#4] + 0 | [Type; String; A + 1; x == A#3] + 1 |-
  x#5 ≡ x#4
[Type; String; u; A] + 0 | [Type; String; A + 1] + 1 |-
  A#4A#3

[Type; String; u] + 0 | [Type; String] + 1 |-
  A#4A#4

[Type; String; u] + 0 | [Type; String; u] + 0 |-
  x = Type#1; x#4(x = Type#1; x#3)#2
[Type; String; u] + 0 | [Type; String] + 1 |-
  x = Type#1; x#4 ≡ x = Type#1; x#3
[Type; String; u; x == Type#1] + 0 | [Type; String; x == Type#1] + 1 |-
  x#4 ≡ x#3


(A : Type) => (A : Type)


1 : (A : Type) => (x : A) => id A x

2 : (A : Type) => (x : A) =>
  (((id : _A) (A : _B) : _C) (x : _D) : _E)

3 : (A : Type) => (x : A) =>
  (((id : (A : Type) -> (x : A) -> A) (A : Type) : (x : A) -> A) (x : A) : A)


(abc) => abd


f(f(f(f(f(f(M))))))


[Type; String; u] + 0 | [Type; String; u] + 0 |-
  (A : Type#1) -> (x = A#4 Type#1; x#5)((A : Type#1) -> (x = A#3 Type#1; x#4))#2
[Type; String; u] + 0 | [Type; String] + 1 |-
  (A : Type#1) -> (x = A#4 Type#1; x#5)(A : Type#1) -> (x = A#3 Type#1; x#4)
[Type; String; u; A] + 0 | [Type; String; A + 1] + 1 |-
  x = A#4 Type#1; x#5 ≡ x = A#3 Type#1; x#4
[Type; String; u; A; x = A#4 Type#1] + 0 | [Type; String; A + 1; x = A#3 Type#1] + 1 |-
  x#5 ≡ x#4
[Type; String; u; A] + 0 | [Type; String; A + 1] + 1 |-
  A#4 Type#1A#3 Type#1
[Type; String; u; A] + 0 | [Type; String; A + 1] + 1 |-
  A#4 Type#1A#3 Type#1

[Type; String; u] + 0 | [Type; String; u] + 0 |-
  (A : Type#1) -> A#4((A : Type#1) -> A#3)#2
[Type; String; u] + 0 | [Type; String] + 1 |-
  (A : Type#1) -> A#4(A : Type#1) -> A#3
[Type; String; u; A#4] + 0 | [Type; String; A#4] + 1 |-
  A#4A#3
[Type; String; u] + 0 | [Type; String] + 1 |-
  A#4A#4

[Type; String; u] + 0 | [Type; String; u] + 0 |-
  (A : Type#1) -> (B : Type#1) -> A#4((A : Type#1) -> (B : Type#1) -> (A#3)#3)#2

[Type; String; u] + 0 | [Type; String] + 1 |-
  (A : Type#1) -> (B : Type#1) -> A#4(A : Type#1) -> (B : Type#1) -> (A#3)#3
[Type; String; u; A#4] + 0 | [Type; String; A#4] + 1 |-
  (B : Type#1) -> A#4(B : Type#1) -> (A#3)#3
[Type; String; u; A#4; B] + 0 | [Type; String; A#4; B] + 1 |-
  A#4(A#3)#3
[Type; String; u; A#4; B] + 0 | [Type; String; A#4] + 1 |-
  A#4A#3


3 | [Type; String; u] | [Type; String; u] |-
  (A : Type#1) -> (B : Type#1) -> A#4((A : Type#1) -> (B : Type#1) -> (A#3)#3)#2
3 | [Type; String; u] | [Type; String; u] |-
  (A : Type#1) -> (B : Type#1) -> A#4((A : Type#1) -> (B : Type#1) -> (A#3)#3)#2
3 | [Type; String; u] | [Type; String] |-
  (A : Type#1) -> (B : Type#1) -> A#4(A : Type#1) -> (B : Type#1) -> (A#3)#3
4 | [Type; String; u; A#4] | [Type; String; A#4] |-
  (B : Type#1) -> A#4(B : Type#1) -> (A#3)#3
4 | [Type; String; u; A#4; B] | [Type; String; A#4; B] |-
  A#4(A#3)#3
4 | [Type; String; u; A#4; B] | [Type; String; A#4] |-
  A#4A#4

[Type; String; u]#3 | [Type; String; u]#3 |-
  (A : Type#1) -> (x = _; A#4)((A : Type#1) -> A#3)#2
[Type; String; u]#3 | [Type; String]#3 |-
  (A : Type#1) -> (x = _; A#4)(A : Type#1) -> A#3
[Type; String; u; A#4]#4 | [Type; String; A#4]#4 |-
  (x = _; A#4)A#3
[Type; String; u; A#4; x]#5 | [Type; String; A#4]#4 |-
  (A#4)A#3


[Type; String; u]#3 | [Type; String; u]#3 |-
  x = _; (A : Type#1) -> A#5((A : Type#1) -> A#3)#2
[Type; String; u]#3 | [Type; String]#3 |-
  x = _; (A : Type#1) -> A#5(A : Type#1) -> A#3
[Type; String; u; x]#4 | [Type; String]#3 |-
  (A : Type#1) -> A#5(A : Type#1) -> A#3
[Type; String; u; x]#5 | [Type; String]#3 |-
  (A : Type#1) -> A#5(A : Type#1) -> A#3


[Type; String]#2 | [Type; String]#2 |-
  x = _; (A : Type#1) -> A#4(A : Type#1) -> A#3
[Type; String; x = _; ]#3 | [Type; String]#2 |-
  (A : Type#1) -> A#4(A : Type#1) -> A#3
[Type; String; x = _; A] | [Type; String; A] |-
  A#4A#3

[Type; String]#2 | [Type; String]#2 |-
  x = _; (A : Type#1) -> A#4(A : Type#1) -> A#3

[Type; String]#2 | [Type; String]#2 |-
  x = (A : Type#1) -> A#3; (B : Type#1) -> x#3(B : Type#1) -> (A : Type#1) -> A#4
[Type; String; x = (A : Type#1) -> A#3; B#3]#4 | [Type; String; B#3]#4 |-
  x#3(A : Type#1) -> A#4

| [Type; String]#4
| [Type; String; B#3]#4 |-
  (A : Type#1) -> A#3(A : Type#1) -> A#4
| [Type; String; A#4]#5
| [Type; String; B#3; A#4]#5 |-
  A#3A#4
| [Type; String; A#4]#5
| [Type; String; B#3; A#4]#5 |-
  A#4A#4


B#3#{((C : Type#1) -> C#4)}#3


received : B#3#{((C : Type#1) -> C#4)}#3
expected : (D : Type#1) -> D#4

((B : Type) -> B#3)#3

((x => x\0)[] N)[K] |-> x\0[N[K]]

(f : (B : Type) -> B#3) =>
  (f#3 : ((B : Type) -> B#3)#3) ((C : Type#1) -> C#4)

B#3#(C : Type#1) -> C#4][]

B#3#{((C : Type#1) -> C#4)}#3


M : ((x : A) -> B)#{Δ}
----------------------
M N : B#{N}#{Δ}

M : ((x : A) -> B)#{Δ}
--------------------------
M N : ((x : A) => B)#{Δ} N

M : ((x : A) -> B)#{Δ}
--------------------------
M N : _T N

((x : A) => B)[x := N][Δ]((x : _C) => _D)[x := N][]

M : ((x : A) -> B)[Δ]  ((x : A) => B)[Δ] N ≡ _T N
-------------------------------------------------
M N : _T N

M N : _B#{x : _A := N}

M : ((x : A) -> B)#{Δ}
----------------------
M N : B#{Δ}#{}#{N}

B#{N}#{Δ}

Γ |- MB
-------------------
Γ, A |- M[]B[]

Memory

Header

size color tag
2 5
color tag extend
2 5 true
type 'a list =
  | Nil
  | Cons of ('a * 'a list)

// to
List : (A : Data) -> A;
List = A =>
  Nil | Cons (hd : A, tl : List A);

Debugger

x = #debug 1;

Effect

// simple, single monad effects
Γ, x : A |- B : Type  Γ, x : A |- E : (y : Type) -> Type
--------------------------------------------------------
Γ |- (x : A) -[E]> B : Type

// generalized unions
Γ |- A : Type  Γ |- M : A  Γ |- N : A
-------------------------------------
Γ |- M | N : A

// symbols instead of String would be dope
Log = K => (tag : String, witness : tag | "log" => K == Unit | _ => Never);
Read = K => (tag : String, witness : tag | "read" => K == String | _ => Never);

// handler just applies effect
handler : <A, E>(
  init : () -[E]> A,
  cb : <K>(eff : E K, k : (x : K) -> A) -> A
);
f : () -[Log | Read]> String = _;

() = handle f (<K>(eff : (Log | Read) K, k) -> _);

// what is a (Log | Read) K?
(Log | Read) K == (
  tag : String,
  witness :
    tag
    | "log" => K == Unit
    | "read" => K == String
    | _ => Never
)


(Log | Read) K
(x => Log x | x => Read x) K // eta
(x => Log x | Read x) K // extrusion
Log K | Read K // beta
// delta
(K => (tag : String, witness : tag | "log" => K == Unit | _ => Never)) K
| (K => (tag : String, witness : tag | "read" => K == String | _ => Never)) K
// beta
(tag : String, witness : tag | "log" => K == Unit | _ => Never)
| (tag : String, witness : tag | "read" => K == String | _ => Never)
// extrusion + pattern merge
(tag : String, witness : tag | "log" => K == Unit | "read" => K == String | _ => Never)

(Log | Read) K == (
  tag : String,
  witness :
    tag
    | "log" => K == Unit
    | "read" => K == String
    | _ => Never
)


// symbols instead of String would be dope
Log = K => (tag : Bool, tag (K == Unit) Never);
Read = K => (tag : Bool, tag Never (K == String));

// handler just applies effect
handler : <A, E>(
  init : () -[E]> A,
  cb : <K>(eff : E K, k : (x : K) -> A) -> A
);
f : () -[Log | Read]> String = _;

() = handle f (<K>(eff : (Log | Read) K, k) -> _);

// what is a (Log | Read) K?
(Log | Read) K == (
  tag : String,
  witness :
    tag
    | "log" => K == Unit
    | "read" => K == String
    | _ => Never
)


Log = K => (tag : Bool, tag (K == Unit) Never);
Read = K => (tag : Bool, tag Never (K == String));

(Log | Read) K
// eta
(x => Log x | x => Read x) K
// extrusion
(x => Log x | Read x) K
// beta
Log K | Read K
// delta
((K => (tag : Bool, tag (K == Unit) Never))
| (K => (tag : Bool, tag Never (K == String)))) K
// beta
(tag : Bool, tag (K == Unit) Never)
| (tag : Bool, tag Never (K == String))
// extrusion
(tag : Bool, (tag (K == Unit) Never) | (tag Never (K == String)))
// extrusion
(tag : Bool, (tag (K == Unit) | tag Never) (Never | K == String))
// extrusion
(tag : Bool, tag ((K == Unit) | Never) (Never | K == String))
// refute
(tag : Bool, tag (K == Unit) (K == String))


K M | K N |-> K (M | N)
M K | N K |-> (M | N) K

(tag (K == Unit) Never) | (tag Never (K == String))

((tag (K == Unit)) Never) | ((tag Never) (K == String))
((tag (K == Unit | Never)) Never) | ((tag (K == Unit | Never)) (K == String))
tag (K == Unit | Never) (Never | K == String);

  tag (K == Unit) | tag Never |-> tag (K == Unit | Never)


(Log | Read) K == (tag : Bool, tag (K == Unit) (K == String))




M + N
M |-> VM     N |-> VN

VM + VN

(b => x => b | true => x | false => 1) true (1 + 2 + 3 + 4)

(x => x + x + 10) (1 + 2 + 3 + 4)
10 + 10 + 10

(x => x + x + x) (1 + 2 + 3 + 4)
(1 + 2 + 3 + 4) + (1 + 2 + 3 + 4) + (1 + 2 + 3 + 4)

(x = 1 + 2 + 3 + 4; x + x + x)


(x => M) N |-> (x = N; M)
(x = N; C<x>) |-> (x = N; C<N>)

(x = 1 + 2 + 3 + 4; x + x + x)
(x = 1 + 2 + 3 + 4; (_ + x + x)<x>)
(x = 1 + 2 + 3 + 4; (_ + x + x)<1 + 2 + 3 + 4>)
(x = 1 + 2 + 3 + 4; (1 + 2 + 3 + 4) + x + x)
b => (x = 1 + 2 + 3 + 4; x + x + (b | true => x | false => 0))

Γ |- A : Type
--------------------------
Γ, x : A |- @typeof x == A

Γ, x : A |- B : Type
-------------------------------------------
Γ |- @typeof ((x : A) => M) == (x : A) -> B

Γ, x : A |- @typeof x : Type
---------------------
Γ |- x : @typeof x


M : ((x : A) -> B)[Δ]  ((x : A) => B)[Δ] N ≡ _T N
-------------------------------------------------
M N : _T N

Γ |- M((x : A) -> B)[Δ]  Γ |- NA[Δ]
-----------------------------------------
Γ |- M N((x : A) => B) N

Γ |- M((x : A) -> B)[Δ]  Γ |- NA[Δ]
-----------------------------------------
Γ |- M N((x : A) => B) N

Γ |- M((x : A) -> B)[Δ]  Γ |- NA[Δ]
-----------------------------------------
Γ |- M N(_T : (_ : _A) -> Type) N


M : ((x : _A) -> B)[Δ]  N : _A[Δ]
-----------------------------------------
M N : (_T : (_x : _A) -> Type)[] N

M N : _x : _A[] = N; (_T : (_x : _A) -> Type)[[]]

M N : (_T : (_x : _A) -> Type)[] N


M : ((x : A) -> B)[Δ]  N : A[Δ]
-----------------------------------------
M N : ((x : A) => B)[Δ] N


M : ((x : A) -> B)[Δ]  N : A[Δ]
-------------------------------
M N : ((x : A) => B)[Δ] N



failwith "a"

x.y <- failwith "a"
setfield (goto 1)


x.y <- failwith "a"


map f l = map f l;

map f l =
  l
  | [] => []
  | hd :: tl => f hd :: map f tl;


rec : <T, a>(f : (self : <b>(l : b < a) -> T b) -> T a) -> T a;

match x with
| l -> _
| exception Not_valid -> _

try
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment