我正在转换AST并且需要的不仅仅是简单的模式匹配,因此需要统一算法。
虽然这是针对.NET项目的,但我知道我可以与.NET PROLOG实现互操作,我只需要嵌入统一算法; PROLOG有点矫枉过正。
如果我能用F#编写的“Martelli,Montanari:一种高效的统一算法”,这将是完美的,但我会满足于任何功能语言,包括HASKELL并转换为F#。
答案 0 :(得分:2)
一般来说,在SO上提问时分享您的尝试是一种很好的做法。人们通常不会为您的问题提供完整的解决方案 - 当您有具体问题或提示如何解决问题时,只需答案。
所以,我会分享一些关于一般方法的提示,但它不是一个完整的解决方案。 首先,您需要以某种方式表示您的AST。在F#中,您可以使用受歧视的联合做到这一点。以下内容支持变量,值和函数应用程序:
type Expr =
| Function of string * Expr list
| Variable of string
| Value of int
统一是一个函数,它将表达式列表统一为(Expr * Expr) list
类型并返回变量赋值(将表达式Expr
赋值给变量名string
):
let rec unify exprs =
match exprs with
// Unify two variables - if they are equal, we continue unifying
// the rest of the constraints, otherwise the algorithm fails
| (Variable s1, Variable s2)::remaining ->
if s1 = s2 then unify remaining
else failwith "cannot unify variables"
// Unify variable with some other expression - unify the remaining
// constraints and add new assignment to the result
| (Variable s, expr)::remaining
| (expr, Variable s)::remaining ->
let rest = unify remaining
// (s, expr) is a tuple meaning that we assign 'expr' to variable 's'
(s, expr)::rest
// TODO: Handle remaining cases here!
| _ -> failwith "cannot unify..."
您需要添加一些案例。最重要的是,将Function
与Function
统一意味着您需要检查函数名称是否相同(否则失败),然后将所有参数表达式作为新约束添加到remaining
列表中。 ..
答案 1 :(得分:2)
Baader& amp;的完整句法统一Snyder使用union-find将两个结构的节点划分为等价类。然后它会走这些类来构建三角形替换。
因为它使用了union-find,如果你正在寻找一个纯粹功能性的答案,那你就运气不好;没有人知道如何编写功能性联合查找。但是,由于Conchon and Filliâtre(用OCaml编写),我们知道如何编写至少显然功能的持久联合查找。