1
1
mirror of https://github.com/anoma/juvix.git synced 2024-11-27 12:42:36 +03:00
juvix/examples/Example1.mjuvix
2021-12-26 17:12:39 -05:00

224 lines
4.7 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 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.
-- reserved symbols (with their Unicode counterpart):
-- , ; : { } -> |-> := === @ _ \
-- 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.
};
module Example1;
module M;
-- This creates a module called M,
-- which it must be closed with:
end M;
open M; -- comments can follow after ;
close M;
-- import moduleName {names} hiding {names};
import Primitives; -- imports all the public names.
import Backend {LLVM}; -- imports to local scope a var. called LLVM.
import Prelude hiding {Nat, Vec, Empty, Unit};
-- same as before, but without the names inside `hiding`
-- Judgement decl.
-- `x : M;`
-- Nonindexed inductive type declaration:
inductive Nat
{ zero : Nat ;
suc : Nat -> Nat ;
};
-- 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:
inductive Vec (n : Nat) (A : Type)
{
zero : Vec Nat.zero A;
succ : A -> Vec n A -> Vec (Nat.succ n) A;
};
Vec' : Nat -> Type -> Type;
Vec' Nat.zero A := Unit;
Vec' (Vec'.suc n) A := A -> Vec' n A;
inductive Empty{};
exfalso : (A : Type) -> Empty -> A;
exfalso A e := match e {};
neg : Type -> Type;
neg := A -> Empty;
-- 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;
-- 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;
-- So far, we haven't used quantites, here is some examples.
-- 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`.
-- 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;
-- Tensor product type.
f' : [ x :1 A ] -> B;
f' x := em x;
-- Pattern-matching on tensor pairs;
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.
-- More inductive types.
inductive Id (A : Type) (x : A)
{
refl : Id A x;
};
a-is-a : a = a;
a-is-a := refl;
-- Where
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';
}
-- `Let` can appear in type level definition
-- 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;
end Example1;
-- 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:
-- print e; print out the internal representation for e, without normalising it.
-- eval e; compute e and print it out;