如何在OCaml中实现lambda-calculus?

问题描述 投票:1回答:3

在OCaml中,似乎“有趣”是我的绑定操作符。 OCaml有内置替代吗?如果是,如何实施?是用de Bruijn指数实现的吗?

只是想知道如何在OCaml中实现无类型的lambda演算,但是没有找到这样的实现。

ocaml lambda-calculus
3个回答
1
投票

OCaml不执行正常顺序减少并使用按值调用语义。 lambda calculus的Some terms具有这种evaluation strategy无法达到的正常形式。

The Substitution Model of Evaluation,以及How would you implement a beta-reduction function in F#?


3
投票

作为Bromind,我也不明白你的意思是说“OCaml有内置替代吗?”

关于lambda-calculus再一次我真的不明白但是,如果你在谈论编写某种lambda-calculus解释器,那么你需要先定义你的“语法”:

(* Bruijn index *)
type index = int

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

所以(λx.x) y将是(λ 0) 1和我们的语法App(Lam (Var 0), Var 1)

现在你需要实现减少,替换等。例如,您可能有这样的事情:

(* 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)

正如您所看到的,OCaml代码只是直接重写定义。

现在小步减少:

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'

例如,您可以评估(λx.x) y

eval (App(Lam (Var 0), Var 1))
- : term = Var 1

1
投票

我并不完全理解你的意思是说“OCaml是否有内置替换?......”,但关于如何在OCaml中实现lambda-calculus,你确实可以使用fun:只需替换所有lambdas fun,例如:对于教堂的数字:你知道zero = \f -> (\x -> x)one = \f -> (\x -> f x),所以在Ocaml,你有

let zero = fun f -> (fun x -> x)
let succ = fun n -> (fun f -> (fun x -> f (n f x)))

succ zero按照你的预期给你one,即fun f -> (fun x -> f x)(为了突出它,你可以试试(succ zero) (fun s -> "s" ^ s) ("0")(succ zero) (fun s -> s + 1) (0))。

据我记忆,你可以和letfun一起改变评估策略,但要确认......


N.B。:我把所有的括号都说成清楚,也许有些可以删除。

© www.soinside.com 2019 - 2024. All rights reserved.