我正在尝试使用数学lambda表示法为函数实现letrec,但我遇到了困难。我的任务说let可以定义为
p(e1) U (p(e2) - {x})
并且letrec可以定义为
(p(e1) - {f x}) U (p(e2) - {f})
我已成功实现let在表达式中查找freevars,但我正在努力实现letrec:
let rec fv (e:expr) : S.t = match e with
| Id name -> S.singleton name
| Value x -> S.empty
| Lambda(name, body) -> S.remove name (fv body)
| Let(name, def, body) -> S.union (fv def) (S.diff (fv body) (S.singleton name))
| App (e1, e2) | Add (e1, e2) | Sub (e1, e2) | Mul (e1, e2) | Div (e1, e2) | Lt (e1, e2) | Eq (e1, e2) | And (e1, e2) -> S.union (fv e1) (fv e2)
有人可以告诉我如何做到这一点?我必须使用Lambda吗?在这一点上我很丢失,只是试图遵循定义的实现必须在我的方面做得不正确,因为我无法让它工作。
答案 0 :(得分:1)
多次阅读你的问题之后,我意识到你正在尝试计算这样一个表达式的自由变量:
let rec x = e1 in e2
let rec
的本质是x
中e1
的出现被用来指代正在定义的x
的值。因此x
中的e1
不是免费的。就像非递归let
一样,x
中的e2
也不是免费的。它绑定到值e1
。
所以我认为实现看起来像这样:
(p(e1) - {x}) U (p(e2) - {x})
你给出的定义对我来说没有意义,特别是因为f
没有明显的含义。
可以想象将此形式限制为x是函数的情况。也许那就是作业告诉你的。
如果你提供更多细节,也许对这些事情有点精通的人可以提供帮助。
答案 1 :(得分:0)
我同意Jeffrey的观点,这里的信息不足。无论如何,我会给出一个实现,因为问题相当简单:
type term =
| Var of string
| App of term * term
| Lam of string * term
| Let of string * term * term
| Letrec of (string * term) list * term
module S = Set.Make (String)
let rec free = function
| Var name -> S.singleton name
| App (f, x) -> S.union (free f) (free x)
| Lam (arg, body) -> S.remove arg (free body)
| Let (name, term, body) ->
S.union (free term) (S.remove name (free body))
| Letrec (rec_terms, body) ->
S.diff
(List.fold_left (fun set (_, term) ->
S.union set (free term))
(free body) rec_terms)
(S.of_list (List.map fst rec_terms))
请注意,这对rec
绑定条款没有限制。如果您只允许那里的功能,那么您可以修改term
以便轻松地反映这一点。