使用Ocaml中的类型查找MAX

使用Ocaml中的类型查找MAX,ocaml,Ocaml,首先,我定义了查找最大值的类型 type my_val = NUM of int | PLUS of my_val * val | MULT of my_val * val | MAX of my_val list 因此,MAX[NUM 9,NUM 20,NUM 3]应该是20。这就是我想做的 我应该做一个函数来计算val的计算结果 这是我写的 let rec eval: my_val -> int = fun given

首先,我定义了查找最大值的类型

type my_val = NUM of int
           | PLUS of my_val * val
           | MULT of my_val * val
           | MAX of my_val list
因此,
MAX[NUM 9,NUM 20,NUM 3]
应该是20。这就是我想做的

我应该做一个函数来计算
val
的计算结果

这是我写的

let rec eval: my_val -> int = fun given ->
    match given with
    | NUM i -> i
    | PLUS (i, j) -> eval(i) + eval(j)
    | MULT (i, j) -> eval(i) * eval(j)
    | MAX i -> 
                (match i with
                | [] -> 0
                | my_hd::[] -> eval(my_hd)
                | my_hd::my_tl -> if eval(my_hd) < eval(my_tl.hd) then eval(my_tl)
                                  else eval(my_hd::my_tl.tl))


let rec eval:my_val->int=fun given->
匹配
|数值i->i
|加(i,j)->eval(i)+eval(j)
|多(i,j)->评估(i)*评估(j)
|最大i->
(与…匹配)
| [] -> 0
|my_hd::[]->eval(my_hd)
|my_hd::my_tl->如果eval(my_hd)
问题出现在
my\u hd
行中

它给了我这个错误

未绑定记录字段hd

我想这是因为我试图比较我的_tl.hd的值,它的类型是我的_val


但是我想不出其他方法来解决这个问题。

在OCaml中,
应用于变量名时意味着记录访问
my_tl.hd
表示您正试图访问记录的记录字段
my_tl
。编译器告诉您,这将不起作用,因为范围中没有名为
hd
的记录字段<当然,code>my_tl
也不是一个记录,但编译器还没有做到这一点

您似乎想使用的是
List.hd
函数,然后是
List.tl
函数。不过,我建议不要使用这些,因为它们不安全。如果给他们一张空名单,他们就会被炸飞

相反,您可能希望使用模式从列表中提取前两个元素:

  | my_hd1::my_hd2::my_tl ->
    if eval(my_hd1) < eval(my_hd2) then
      eval(my_hd2 :: my_tl)
    else
      eval(i)
| my_hd1::my_hd2::my_tl->
如果eval(my_hd1)
这将永远不会失败,如果您忘记只讨论一个元素的情况,编译器将告诉您

最后,使用
i
j
作为非计数器值的变量名会让您看起来很奇怪<如果您有多个相同类型的“主要”值,则代码>a
b
,或
x
y
更常用作缩写,但在这种情况下,您确实应该使用更多描述性名称


编辑:同样,您仍然不应该在函数应用程序中使用括号。当你在某个时候添加另一个你已经习惯的参数,并且得到奇怪的类型错误时,这会让你更加困惑。

在OCaml中,
当应用到变量名时意味着记录访问
my_tl.hd
表示您正试图访问记录的记录字段
my_tl
。编译器告诉您,这将不起作用,因为范围中没有名为
hd
的记录字段<当然,code>my_tl
也不是一个记录,但编译器还没有做到这一点

您似乎想使用的是
List.hd
函数,然后是
List.tl
函数。不过,我建议不要使用这些,因为它们不安全。如果给他们一张空名单,他们就会被炸飞

相反,您可能希望使用模式从列表中提取前两个元素:

  | my_hd1::my_hd2::my_tl ->
    if eval(my_hd1) < eval(my_hd2) then
      eval(my_hd2 :: my_tl)
    else
      eval(i)
| my_hd1::my_hd2::my_tl->
如果eval(my_hd1)
这将永远不会失败,如果您忘记只讨论一个元素的情况,编译器将告诉您

最后,使用
i
j
作为非计数器值的变量名会让您看起来很奇怪<如果您有多个相同类型的“主要”值,则代码>a
b
,或
x
y
更常用作缩写,但在这种情况下,您确实应该使用更多描述性名称


编辑:同样,您仍然不应该在函数应用程序中使用括号。这只会让你更加困惑,当你在某个时候添加另一个你已经习惯的参数,并得到奇怪的类型错误。

谢谢。但是
eval(my_hd2::my_tl)
给了我这个错误<代码>错误:此变量表达式的类型应为expr。构造函数::不属于类型expr右侧,这是您自己的代码中出现的类型错误
eval
不采用列表,而是采用
my_val
(或
expr
,视类型而定)。您必须使用
MAX
构造函数从列表中创建这样的值:
eval(MAX(my_hd2::my_tl))
。但是现在您还将在
eval(i)
上得到一个错误,因为
i
(或者
my_hd::my_tl.tl
来自原始代码)也不是
my_val
。如果你只是把它包装在
MAX
中,函数将无限递归,因为你每次都传递相同的值。这是一个逻辑错误,你需要修正。谢谢。但是
eval(my_hd2::my_tl)
给了我这个错误<代码>错误:此变量表达式的类型应为expr。构造函数::不属于类型expr右侧,这是您自己的代码中出现的类型错误
eval
不采用列表,而是采用
my_val
(或
expr
,视类型而定)。您必须使用
MAX
构造函数从列表中创建这样的值:
eval(MAX(my_hd2::my_tl))
。但是现在您还将在
eval(i)
上得到一个错误,因为
i
(或者
my_hd::my_tl.tl
来自原始代码)也不是
my_val
。如果你只是把它包装在
MAX
中,函数将无限递归,因为你每次都传递相同的值。这是一个需要修复的逻辑错误。