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
答案 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
是某种数据类型的构造函数,并且您正在尝试将第一个参数(必须是该数据类型的值)与该构造函数进行模式匹配。那不是你想要的。
要定义一个接受参数x
,y
和z
的函数,您应该写一下:
fun substitute (x, y, z) = ...
或者,如果你想拼出参数类型:
fun substitute (x: Name, y: Expr, z: Expr) = ...
PS:在函数正文中编写x = z
,但这不起作用,因为x
和z
是不同类型的值 - 它们不可能相等彼此。