Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to implement lambda-calculus in OCaml?

In OCaml, it seems that "fun" is the binding operator to me. Does OCaml have built-in substitution? If does, how it is implemented? is it implemented using de Bruijn index?

Just want to know how the untyped lambda-calculus can be implemented in OCaml but did not find such implementation.

like image 511
arslan Avatar asked Feb 15 '26 03:02

arslan


1 Answers

As Bromind, I also don't exactly understand what you mean by saying "Does OCaml have built-in substitution?"

About lambda-calculus once again I'm not really understand but, if you talking about writing some sort of lambda-calculus interpreter then you need first define your "syntax":

(* Bruijn index *)
type index = int

type term =
  | Var of index
  | Lam of term
  | App of term * term

So (λx.x) y will be (λ 0) 1 and in our syntax App(Lam (Var 0), Var 1).

And now you need to implement your reduction, substitution and so on. For example you may have something like this:

(* identity substitution: 0 1 2 3 ... *)
let id i = Var i

(* particular case of lift substitution: 1 2 3 4 ... *)
let lift_one i = Var (i + 1)

(* cons substitution: t σ(0) σ(1) σ(2) ... *)
let cons (sigma: index -> term) t = function
  | 0 -> t
  | x -> sigma (x - 1)

(* by definition of substitution:
       1)  x[σ] = σ(x)
       2)  (λ t)[σ] = λ(t[cons(0, (σ; lift_one))])
               where (σ1; σ2)(x) = (σ1(x))[σ2]
       3)  (t1 t2)[σ] = t1[σ] t2[σ]
*)
let rec apply_subs (sigma: index -> term) = function
  | Var i -> sigma i
  | Lam t -> Lam (apply_subs (function
                              | 0 -> Var 0
                              | i -> apply_subs lift_one (sigma (i - 1))
                             ) t)
  | App (t1, t2) -> App (apply_subs sigma t1, apply_subs sigma t2)

As you can see OCaml code is just direct rewriting of definition.

And now small-step reduction:

let is_value = function
  | Lam _ | Var _ -> true
  | _ -> false

let rec small_step = function
  | App (Lam t, v) when is_value v ->
     apply_subs (cons id v) t
  | App (t, u) when is_value t ->
     App (t, small_step u)
  | App (t, u) ->
     App (small_step t, u)
  | t when is_value t ->
     t
  | _ -> failwith "You will never see me"

let rec eval = function
  | t when is_value t -> t
  | t -> let t' = small_step t in
         if t' = t then t
         else eval t'

For example you can evaluate (λx.x) y:

eval (App(Lam (Var 0), Var 1))
- : term = Var 1
like image 188
vonaka Avatar answered Feb 17 '26 11:02

vonaka



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!