Miki beta - User manual

Back

#0. STLC as an example

We have the definition of `Simply Typed Lambda Calculus` below.

#1. Define types for each term

Let's define STLC terms. You should construct your terms by combining representation of types. We call the representation of type Code. Code is defined in Miki Beta as follows.

Code consists of five elements: Represent each type of terms by using Code. STLC terms can be represented as follows.

term-indexnameRepresentation of type
0thvaluePlus (PS, Times (PS, I 1))
1stexpPlus (I 0, Times (I 1, I 1))
2ndtypPlus (PS, Times (I 2, I 2))
3rdenvPlus (U, Times (Times (I 1, I 2), I 3))
4thjudgementTimes (I 3, Times (I 1, I 2))

For simplicity, we refer to each term-index as `{term's name}_i` from here. `value_i` refers to the index 0, and `env_i` to 3 for example.

#2. Define each term and how to draw it in OCaml program

You should define each term in OCaml program, and give them to Miki Beta. Let me show how to define `value` term as an example.
`value` term consists of two alternatives: `var` and `abst`. For each alternative, you should define the three features:
  1. constructor's name (string typed)
  2. representation of the type (Code typed)
  3. renderer function
We know that each three features for `var` and `abst` are as follows.

1.constructor's name:"var"
2.representation of the type:PS
3.renderer function:x
(when the string parameter for PS is `x`)
1.constructor's name:"abst"
2.representation of the type:Times (PS, I expr_i)
3.renderer function:λx. y
(when the string parameter for PS is `x` and `I expr_i` is rendered as `y`)

As OCaml program, you should define the three features as a tuple. Then collect them in a single list.
let value_def =
[("var",
  PS,
  fun t -> t 0);
 ("abst",
  Times (PS, I expr_i),
  fun t -> combineH [create_str "(λ"; t 0; create_str ". "; t 1; create_str ")"])
]
After defining the list of tuples for each term (say `value_def`, ... , `judgement_def`), then store all of them in one list named `termDefs`. They should be paired with string representation of meta variable (how you want to draw meta variable for the termX). Note that each of list indexes corresponds to a term's ordinal number. You define a module, which contains the list `termDefs` and an int `top_i`. `top_i` is the ordinal number for the outermost term. Both `termDefs` and `top_i` must be declared with these names.
module Terms = struct
  (* top_i : int *)
  (* The ordinal number for the outermost term *)
  let top_i = judgement_i

  (* termDefs : string * termdef_t list *)
  (* list of definitions of each terms' name, types, and how to draw them *)
  let termDefs = [("v", value_def); ("e", exp_def); ("t", typ_def); ("env", env_def); ("judgement", judgement_def)]
end
Pass the defined module to a functor in Miki Beta `Fix.F`, and you will finally get the wrapped module that is needed to create the GUI world. Let us call the module `Fixs`.
module Fixs = Fix.F (Terms)

#3. Define a list of axioms and inference rules in OCaml program

Lastly, we would like to define axioms and inference rules in STLC. We should use the module `Fixs` here. The module `Fixs` enables two operation for x-th term: With these two interfaces, you can define your rules.
(* Functions to construct each term *)
let var s = Fixs.make value_i "var" [s] []
let abst ps e = Fixs.make value_i "abst" [ps] [e]
let var s = Fixs.make value_i "var" [s] []
let valu v = Fixs.make expr_i "val" [] [v]
let arrow t1 t2 = Fixs.make type_i "arr" [] [t1; t2]
let app e1 e2 = Fixs.make expr_i "app" [] [e1; e2]
let judgement e ve t = Fixs.make eval_i "eval" [] [e; ve; t]

(* `var` axiom *)
let rule_vars () =
  let e = Fixs.make_meta expr_i in
  let t = Fixs.make_meta type_i in
  let env = Fixs.make_meta env_i in
  Axiom (judgement (cons e t env) e t)

(* `abst` inference rule *)
let rule_abst () =
  let x = meta_string () in
  let e = Fixs.make_meta expr_i in
  let abst_e = valu (abst x e) in
  let t1 = Fixs.make_meta type_i in
  let t2 = Fixs.make_meta type_i in
  let env = Fixs.make_meta env_i in
  let env' = cons (valu (var x)) t1 env in
  Infer (judgement env abst_e (arrow t1 t2),
         [Infer (judgement env' e t2, [])])
...
(* infer_rule_list : (unit -> rule_t) list *)
let infer_rule_list = [rule_vars; rule_abst; ... ]
Note that you should declare a list of all rules and it must be named `infer_rule_list`. Each element is the type of rule_t, which has two constructors:

#4. Build and execute

Once you've finished to define the terms and rules, you can build them.

Back