我是初学者,我使用的术语可能不准确。
我有
type t = True | False | If of t * t * t | Int of int | Plus of t * t | GT of t * t
let isval t =
match t with
True|False -> true
| Int _ -> true
| _ -> false
我想实现一个eval函数。
let rec step t =
match isval t with
true -> raise NormalForm
| false -> match t with
If(t1, t2, t3) when t1=True -> t2
| If(t1, t2, t3) when t1=False -> t3
| Plus(t1, t2) -> t1+t2
| GT(t1, t2) -> t1>t2
| _ -> raise NormalForm;;
Plus(t1, t2) -> t1+t2
发生错误,说“此表达式的类型为t,但表达式的类型为int”。
有什么问题?我该如何解决?
答案 0 :(得分:3)
正如编译器所说+
运算符在int上工作。但是你将它应用于t
类型的子表达式。由于您的类型t
可以代表Plus(True, False)
之类的内容,因此您需要决定实际上如何处理这些案例。
您还需要决定返回类型。您的某些案例似乎正在返回bool
,其他案件返回t
,其他案件则返回int
。从外观上看,您可能希望在所有情况下都返回t
。如果是这样,您将返回Int n
而不是仅仅n
。
(Basile Starynkevitch编写了一些解决这些问题的代码。也许先自己先考虑一下然后看看他的代码: - )
答案 1 :(得分:1)
match
表达式(遗憾的是)没有结束标记。对于嵌套match
,您必须使用括号或begin
... end
,例如代码
match x with
SomePattern y -> begin
match y with
AnyotherThing -> ....
YetAnotherPattern z -> ....
end
并且您遇到了类型问题:step
函数在执行int
时提供t1+t2
,在执行bool
时提供t1>t2
;这是不可能的,函数应该返回一些已知的(单一)类型。
您可能想要定义
type result_t = NoResult | IntResult of int | BoolResult of bool
并提供IntResult (t1+t2)
或BoolResult (t1>t2)
或者您可以让step
返回一些t
值,即True
,False
,Int (t1+t2)
我会改为编码
let asint = function Int x -> x | _ -> failwith "not an integer"
let rec eval = function
True -> True
| False -> False
| Int x -> Int x
| If (cond,thenpart,elsepart) -> begin
match eval cond with
True -> eval thenpart
| False -> eval elsepart
| _ -> failwith "bad condition"
end
| Plus (l, r) ->
Int (asint (eval l) + asint (eval r))
| GT (l, r) -> begin
if (asint (eval l)) > (asint (eval r)) then
True
else
False
end