在F#中寻求统一算法

时间:2012-03-01 21:33:26

标签: f# unification

我正在转换AST并且需要的不仅仅是简单的模式匹配,因此需要统一算法。

虽然这是针对.NET项目的,但我知道我可以与.NET PROLOG实现互操作,我只需要嵌入统一算法; PROLOG有点矫枉过正。

如果我能用F#编写的“Martelli,Montanari:一种高效的统一算法”,这将是完美的,但我会满足于任何功能语言,包括HASKELL并转换为F#。

2 个答案:

答案 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..."

您需要添加一些案例。最重要的是,将FunctionFunction统一意味着您需要检查函数名称是否相同(否则失败),然后将所有参数表达式作为新约束添加到remaining列表中。 ..

答案 1 :(得分:2)

Baader& amp;的完整句法统一Snyder使用union-find将两个结构的节点划分为等价类。然后它会走这些类来构建三角形替换。

因为它使用了union-find,如果你正在寻找一个纯粹功能性的答案,那你就运气不好;没有人知道如何编写功能性联合查找。但是,由于Conchon and Filliâtre(用OCaml编写),我们知道如何编写至少显然功能的持久联合查找。