2021-12-25 17:43:24 +03:00
|
|
|
|
-- Comments as in Haskell.
|
|
|
|
|
--This is another comment
|
|
|
|
|
------ This is another comment
|
|
|
|
|
-- This is another comment --possible text--
|
|
|
|
|
-- This is a comment, as it is not indent
|
|
|
|
|
-- sensitive. It should be fine.
|
|
|
|
|
|
2021-12-27 01:12:39 +03:00
|
|
|
|
-- reserved symbols (with their Unicode counterpart):
|
|
|
|
|
-- , ; : { } -> |-> := === @ _ \
|
2021-12-25 17:43:24 +03:00
|
|
|
|
-- reserved words:
|
|
|
|
|
-- module close open axiom inductive record options
|
|
|
|
|
-- where let in
|
|
|
|
|
|
|
|
|
|
-- Options to check/run this file.
|
|
|
|
|
options {
|
|
|
|
|
debug := INFO;
|
|
|
|
|
phase := { parsing , check };
|
|
|
|
|
backend := none; -- llvm.
|
|
|
|
|
};
|
|
|
|
|
|
2021-12-26 19:26:39 +03:00
|
|
|
|
module Example1;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
|
|
|
|
module M;
|
|
|
|
|
-- This creates a module called M,
|
|
|
|
|
-- which it must be closed with:
|
2021-12-26 19:26:39 +03:00
|
|
|
|
end M;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
|
|
|
|
open M; -- comments can follow after ;
|
|
|
|
|
close M;
|
|
|
|
|
|
2021-12-26 19:26:39 +03:00
|
|
|
|
-- import moduleName {names} hiding {names};
|
|
|
|
|
import Primitives; -- imports all the public names.
|
|
|
|
|
import Backend {LLVM}; -- imports to local scope a var. called LLVM.
|
2021-12-27 01:12:39 +03:00
|
|
|
|
import Prelude hiding {Nat, Vec, Empty, Unit};
|
2021-12-26 19:26:39 +03:00
|
|
|
|
-- same as before, but without the names inside `hiding`
|
|
|
|
|
|
2021-12-25 17:43:24 +03:00
|
|
|
|
-- Judgement decl.
|
|
|
|
|
-- `x : M;`
|
|
|
|
|
|
|
|
|
|
-- Nonindexed inductive type declaration:
|
|
|
|
|
inductive Nat
|
|
|
|
|
{ zero : Nat ;
|
2021-12-26 19:26:39 +03:00
|
|
|
|
suc : Nat -> Nat ;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
-- Term definition uses := instead of =.
|
|
|
|
|
-- = is not a reserved name.
|
|
|
|
|
-- == is not a reserved name.
|
|
|
|
|
-- === is a reserved symbol for def. equality.
|
|
|
|
|
zero' : Nat;
|
|
|
|
|
zero'
|
|
|
|
|
:= zero;
|
|
|
|
|
|
|
|
|
|
-- Axioms/definitions.
|
|
|
|
|
axiom A : Type;
|
|
|
|
|
axiom a a' : A;
|
|
|
|
|
|
|
|
|
|
f : Nat -> A;
|
|
|
|
|
f := \x -> match x
|
|
|
|
|
{
|
|
|
|
|
zero |-> a ;
|
|
|
|
|
suc |-> a' ;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
g : Nat -> A;
|
|
|
|
|
g Nat.zero := a;
|
|
|
|
|
g (Nat.suc t) := a';
|
|
|
|
|
|
|
|
|
|
-- Qualified names for pattern-matching seems convenient.
|
|
|
|
|
-- For example, if we define a function without a type sig.
|
|
|
|
|
-- that also matches on inductive type with constructor names
|
|
|
|
|
-- appearing in another type, e.g. Nat and Fin.
|
|
|
|
|
|
|
|
|
|
inductive Fin (n : Nat) {
|
|
|
|
|
zero : Fin Nat.zero;
|
|
|
|
|
suc : (n : Nat) -> Fin (Nat.suc n);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
infixl 10 _+_ ; -- fixity notation as in Agda or Haskell.
|
|
|
|
|
_+_ : Nat → Nat → Nat ;
|
|
|
|
|
_+_ Nat.zero m := m;
|
|
|
|
|
_+_ (Nat.suc n) m := Nat.suc (n + m) ;
|
|
|
|
|
|
|
|
|
|
-- Unicode is possible.
|
|
|
|
|
ℕ : Type;
|
|
|
|
|
ℕ := Nat;
|
|
|
|
|
-- Maybe consider alises for types and data constructors:
|
|
|
|
|
-- `alias ℕ := Nat` ;
|
|
|
|
|
|
|
|
|
|
-- The function `g` should be transformed to
|
|
|
|
|
-- a function of the form f. (aka. case-tree compilation)
|
|
|
|
|
|
|
|
|
|
-- Examples we must have to make things interesting:
|
|
|
|
|
-- Recall ; goes after any declarations.
|
|
|
|
|
|
|
|
|
|
inductive Unit { tt : Unit;};
|
|
|
|
|
|
|
|
|
|
-- Indexed inductive type declarations:
|
2021-12-26 19:26:39 +03:00
|
|
|
|
inductive Vec (n : Nat) (A : Type)
|
2021-12-25 17:43:24 +03:00
|
|
|
|
{
|
2021-12-26 19:26:39 +03:00
|
|
|
|
zero : Vec Nat.zero A;
|
|
|
|
|
succ : A -> Vec n A -> Vec (Nat.succ n) A;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
};
|
|
|
|
|
|
2021-12-26 19:26:39 +03:00
|
|
|
|
Vec' : Nat -> Type -> Type;
|
|
|
|
|
Vec' Nat.zero A := Unit;
|
|
|
|
|
Vec' (Vec'.suc n) A := A -> Vec' n A;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
2021-12-27 01:12:39 +03:00
|
|
|
|
inductive Empty{};
|
|
|
|
|
|
|
|
|
|
exfalso : (A : Type) -> Empty -> A;
|
|
|
|
|
exfalso A e := match e {};
|
|
|
|
|
|
|
|
|
|
neg : Type -> Type;
|
|
|
|
|
neg := A -> Empty;
|
|
|
|
|
|
2021-12-25 17:43:24 +03:00
|
|
|
|
-- Record
|
|
|
|
|
record Person {
|
|
|
|
|
name : String;
|
|
|
|
|
age: Nat;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
h : Person -> Nat;
|
|
|
|
|
h := \x -> match x {
|
|
|
|
|
{name = s , age = n} |-> n;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
h' : Person -> Nat;
|
|
|
|
|
h' {name = s , age = n} := n;
|
|
|
|
|
|
2021-12-26 19:26:39 +03:00
|
|
|
|
-- projecting fields values.
|
|
|
|
|
h'' : Person -> String;
|
|
|
|
|
h'' p := Person.name p;
|
|
|
|
|
|
|
|
|
|
-- maybe, harder to support but very convenient.
|
|
|
|
|
h''' : Person -> String;
|
|
|
|
|
h''' p := p.name;
|
|
|
|
|
|
2021-12-25 17:43:24 +03:00
|
|
|
|
-- So far, we haven't used quantites, here is some examples.
|
2021-12-26 19:26:39 +03:00
|
|
|
|
-- We mark a type judgment `x : M` of quantity n as `x :n M`.
|
|
|
|
|
-- If the quantity n is not explicit, then the judgement
|
|
|
|
|
-- is `x :Any M`.
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
2021-12-26 19:26:39 +03:00
|
|
|
|
-- The following says that the term z of type A has quantity 0.
|
|
|
|
|
axiom z :0 A;
|
|
|
|
|
axiom B : (x :1 A) -> Type; -- type family
|
|
|
|
|
axiom T : [ A ] B; -- Tensor product type. usages Any
|
|
|
|
|
axiom T' : [ x :1 A ] B; -- Tensor product type.
|
|
|
|
|
axiom em : (x :1 A) -> B;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
|
|
|
|
-- Tensor product type.
|
2021-12-27 01:12:39 +03:00
|
|
|
|
f' : [ x :1 A ] -> B;
|
2021-12-26 19:26:39 +03:00
|
|
|
|
f' x := em x;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
2021-12-26 19:26:39 +03:00
|
|
|
|
-- Pattern-matching on tensor pairs;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
2021-12-26 19:26:39 +03:00
|
|
|
|
g' : ([ A -> B ] A) -> B; -- it should be the same as `[ A -> B ] A -> B`
|
|
|
|
|
g' (k , a) = k a;
|
|
|
|
|
|
|
|
|
|
g'' : ([ A -> B ] A) -> B;
|
|
|
|
|
g'' = \p -> match p {
|
|
|
|
|
(k , a) |-> k a;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
axiom C : Type;
|
|
|
|
|
axiom D : Type;
|
|
|
|
|
|
|
|
|
|
-- A quantity can annotate a field name in a record type.
|
|
|
|
|
record P (A : Type) (B : A -> Type) {
|
|
|
|
|
proj1 : C;
|
|
|
|
|
proj2 :0 D;
|
|
|
|
|
}
|
|
|
|
|
eta-equality, constructor prop; -- extra options.
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
|
|
|
|
-- More inductive types.
|
|
|
|
|
inductive Id (A : Type) (x : A)
|
|
|
|
|
{
|
|
|
|
|
refl : Id A x;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
a-is-a : a = a;
|
|
|
|
|
a-is-a := refl;
|
|
|
|
|
|
2021-12-27 01:12:39 +03:00
|
|
|
|
-- Where
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
|
|
|
|
a-is-a' : a = a;
|
|
|
|
|
a-is-a' := helper
|
|
|
|
|
where helper := a-is-a;
|
|
|
|
|
|
|
|
|
|
a-is-a'' : a = a;
|
|
|
|
|
a-is-a'' := helper
|
|
|
|
|
where {
|
|
|
|
|
helper : a = a;
|
|
|
|
|
helper := a-is-a';
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-27 01:12:39 +03:00
|
|
|
|
-- `Let` can appear in type level definition
|
2021-12-25 17:43:24 +03:00
|
|
|
|
-- but also in term definitions.
|
|
|
|
|
|
|
|
|
|
a-is-a-3 : a = a;
|
|
|
|
|
a-is-a-3 := let { helper : a = a; helper := a-is-a;} in helper;
|
|
|
|
|
|
|
|
|
|
a-is-a-4 : let {
|
|
|
|
|
typeId : (M : Type) -> (x : M) -> Type;
|
|
|
|
|
typeId M x := x = x;
|
|
|
|
|
} in typeId A a;
|
|
|
|
|
a-is-a-4 := a-is-a;
|
|
|
|
|
|
2021-12-26 19:26:39 +03:00
|
|
|
|
end Example1;
|
2021-12-25 17:43:24 +03:00
|
|
|
|
|
|
|
|
|
-- future:
|
|
|
|
|
-- module M' (X : Type);
|
|
|
|
|
-- x-is-x : (x : X) -> x = x;
|
|
|
|
|
-- x-is-x x := refl;
|
|
|
|
|
-- end M';
|
|
|
|
|
-- open M' A;
|
|
|
|
|
-- a-is-a-5 := a = a;
|
|
|
|
|
-- a-is-a-5 = x-is-x a;
|
|
|
|
|
-- Also, for debugging:
|
|
|
|
|
|
2021-12-27 01:12:39 +03:00
|
|
|
|
-- print e; print out the internal representation for e, without normalising it.
|
2021-12-25 17:43:24 +03:00
|
|
|
|
-- eval e; compute e and print it out;
|