SML:扫描关系列表以获取所有传递关联

时间:2013-06-09 13:18:00

标签: list sml relation smlnj transitive-dependency

我有一个 environment 列表,用于保存变量和值之间的关联,例如env = [("x", 1), ("y", 2), ("z", 3), ...]。我还有另一个替换列表(由模式匹配控制函数返回),它保持变量和模式之间的关联,例如s = [("v", Var_p "z"), ("w", Var_p "v"), ("u", Var_p "w"), ...]。让我们考虑第一对("v", Var_p "z"):我的函数应该检查环境中z对应的值,在vz的值之间创建一个新的关联(即{ {1}})并将其放入环境中。我的这个函数的代码如下。

("v", 3)

此处,fun augment_env ([], e : env) = e | augment_env (s :: srest, e : env) = let val (a, b) = s in case b of Const_p i => [] @ augment_env_with_vars (srest, e) | Var_p x => if (exists (e, x)) then (a, lookup (e, x)) :: augment_env_with_vars (srest, e) end; 是替换列表,sexists是检查环境中是否存在变量并分别查找相应值的函数。此函数的问题是仅适用于直接关联(在示例中,它将lookupv之间的直接关联放入环境中)。它显然不适用于传递关联,除非我多次调用它(我事先不知道它们有多少)。要回忆一下这个例子,在这个函数的末尾,我的环境列表应该是3

你能不能给我一个关于如何修改这个函数的提示,以便与传递关联一起工作?

提前致谢!

1 个答案:

答案 0 :(得分:1)

首先,由于函数lookupaugment_env_with_vars和某些类型未知,因此很难给出精确的提示。

但是,根据您提供的内容进行猜测,可以这样做:

取1

type const = int
type var = string
type env = (var * const) list
datatype value = Const_p of const | Var_p of var

exception Not_found

fun lookup_env (e, v) =
    case e of
        [] => raise Not_found
      | (a, b)::xs => if a = v then b else lookup_env (xs, v)

fun new_env (l, e) =
    case l of
        [] => e
      | (a, b)::xs =>
        case b of
            Const_p _ => new_env (xs, e)
          | Var_p b => new_env (xs, e @ [(a, lookup_env (e, b))])

(* test *)

val e = [("x", 1), ("y", 2), ("z", 3)]
val s = [("v", Var_p "z"), ("w", Var_p "v"), ("u", Var_p "w")]

val test = new_env (s, e)

结果1

val e = [("x",1),("y",2),("z",3)] : (string * int) list
val s = [("v",Var_p "z"),("w",Var_p "v"),("u",Var_p "w")]
  : (string * value) list
val test = [("x",1),("y",2),("z",3),("v",3),("w",3),("u",3)]
  : (var * int) list

但是,如果替换列表中的任何变量出现在其定义之前,new_env将失败。要解决此问题,请在引用lookup_env

之前扫描替换列表

选择2

fun lookup_var (l, v) =
    case l of
        [] => v
      | (a, b)::xs =>
        case b of
            Const_p _ => lookup_var (xs, v)
          | Var_p b => lookup_var (if a = v then (l, b) else (xs, v))

fun new_env2 (l, e) =
    case l of
        [] => e
      | (a, b)::xs =>
        case b of
            Const_p _ => new_env2 (xs, e)
          | Var_p b => new_env2 (xs, e @ [(a, lookup_env (e, lookup_var (l, b)))])

(* test *)

val e = [("x", 1), ("y", 2), ("z", 3)]
val s2 = [("v", Var_p "z"), ("u", Var_p "w"), ("w", Var_p "v")]

val test2 = new_env2 (s2, e)

结果2

val e = [("x",1),("y",2),("z",3)] : (string * int) list
val s2 = [("v",Var_p "z"),("u",Var_p "w"),("w",Var_p "v")]
  : (string * value) list
val test2 = [("x",1),("y",2),("z",3),("v",3),("u",3),("w",3)]
  : (var * int) list

注意交换的" u"和" w"在第二个例子中。