我在 OCaml 中做微分函数,我遇到了一些问题

I'm making differentiating function in OCaml and I have some problems

首先,这是我的代码:

module Problem1 = struct
  type aexp = 
  | Const of int
  | Var of string
  | Power of string * int
  | Times of aexp list
  | Sum of aexp list

  let diff : aexp * string -> aexp
  = fun (exp, var) ->
        match exp with
        |Const a -> Const 0
        |Var x -> if x = var then Const 1 else Var x
        |Power (s, i) -> 
            if s = var then Times[Const i;Power (s, i - 1)] else Power (s, i)
        |Times l ->
            match l with
                |h::t -> Sum[Times[diff (h, var);t];diff (t, var)]
        |Sum m ->
            match m with
                |h::t -> Sum[diff(h, var); diff(t, var)];; 
end

口译员说,

Error: This variant pattern is expected to have type aexp list
       The constructor Sum does not belong to type list

但我希望符号 m 是一个 aexp 列表。 找不到问题所在。

对我来说,这部分看起来不对:Times[diff (h, var);t]。由于 t 是一个 aexp list,您应该使用另一个列表构造函数 ::,使其成为 `Times (diff (h, var) :: t).

如果你把 match .. with .. 放在另一个 match .. with 的盒子里,你需要用 begin 包裹里面的盒子 .. end:

(* I do not check the code is correct *)
let diff : aexp * string -> aexp
  = fun (exp, var) ->
    match exp with
    |Const a -> Const 0
    |Var x -> if x = var then Const 1 else Var x
    |Power (s, i) -> 
        if s = var then Times[Const i;Power (s, i - 1)] else Power (s, i)
    |Times l ->
        begin match l with
        |h::t -> Sum[Times[diff (h, var);t];diff (t, var)]
        end
    |Sum m ->
        match m with
        |h::t -> Sum[diff(h, var); diff(t, var)]

请安装合适的自动缩进工具,例如 tuareg 或 ocp-indent,因为它们可以告诉您正确的程序结构。手印往往会骗过你的眼睛。

实际上你的问题很简单,你会通过使用知道如何缩进 OCaml 代码的工具看到它;-)

看看你的最后几行是如何用 OCaml 压头缩进的:

    |Times l ->
      match l with
        |h::t -> Sum[Times[diff (h, var);t];diff (t, var)]
        |Sum m ->
          match m with
            |h::t -> Sum[diff(h, var); diff(t, var)];; 

是的,没错,因为你在Times l中创建了一个新的模式匹配,Sum m被包含在其中。你应该写

    |Times l -> begin
      match l with
        |h::t -> Sum[Times[diff (h, var);t];diff (t, var)]
      end
    |Sum m ->
       match m with
         |h::t -> Sum[diff(h, var); diff(t, var)];; 

它会工作得很好。

顺便说一句,你会遇到另一个问题,因为你没有写 let rec diff ... 而是 let diff 并且你正在递归调用 diff