比较ML中的不同数据类型

时间:2013-03-01 21:42:11

标签: ml

type Name = string;
datatype Expr = Const of int
    | Var of Name
    | Neg of Expr
    | Plus of Expr * Expr
    | Mult of Expr * Expr
    | App of Fun * Expr
    and Fun = Def of Name * Expr

(* substitute every x in expression z with expression y *)

fun substitute (Name x, Expr y, Expr z) = if x = z then y else z;

我只想比较x和z的字符串值,如果它们是相同的返回y,否则返回z,但我一直收到这个错误?

e.sml:13.33-13.39 Error: non-constructor applied to argument in pattern: Expr
e.sml:13.25-13.31 Error: non-constructor applied to argument in pattern: Expr
e.sml:13.17-13.23 Error: non-constructor applied to argument in pattern: Name
e.sml:13.50 Error: unbound variable or constructor: z
e.sml:13.46 Error: unbound variable or constructor: x
e.sml:13.57 Error: unbound variable or constructor: y
e.sml:13.64 Error: unbound variable or constructor: z

uncaught exception Error
  raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
         ../compiler/TopLevel/interact/evalloop.sml:44.55
         ../compiler/TopLevel/interact/evalloop.sml:296.17-296.20

2 个答案:

答案 0 :(得分:3)

你对substitute的定义并没有多大意义;)。首先,你使用的是类型和模式匹配错误,其次你需要递归替换,而不仅仅是根表达式。

以下是工作版本的草图:

fun substitute(x, e, Const n)      = Const n
  | substitute(x, e, Var y)        = if x = y then e else Var y
  | substiture(x, e, Neg e')       = Neg(substitute(x, e, e'))
  | substitute(x, e, Plus(e1, e2)) = Plus(substitute(x, e, e1), substitute(x, e, e2))
  | ...

您应该可以填写剩余的案例。 App案例需要小心谨慎以避免在函数中意外捕获 - 也就是说,当x与参数变量相同时,您必须避免在体内替换。

如果你热衷于给出类型注释,那么这个函数最好用一个案例写成:

fun substitute(x : Name, e : Expr, z : Expr) =
    case z of
      Const n => z
    | Var y   => if x = y then e else z
    | Neg e'  => Neg(substitute(x, e, e'))
    ...

这相当于前者,这只是一个案例的语法糖。

答案 1 :(得分:1)

您似乎认为函数参数的语法是typename variablename。不是。语法为pattern : typename或仅pattern,其中最简单的模式形式只是变量名。

Name x之类的东西意味着Name是某种数据类型的构造函数,并且您正在尝试将第一个参数(必须是该数据类型的值)与该构造函数进行模式匹配。那不是你想要的。

要定义一个接受参数xyz的函数,您应该写一下:

fun substitute (x, y, z) = ...

或者,如果你想拼出参数类型:

fun substitute (x: Name, y: Expr, z: Expr) = ...

PS:在函数正文中编写x = z,但这不起作用,因为xz是不同类型的值 - 它们不可能相等彼此。