2016-11-03 31 views
0
type aexp = 
    | Const of int 
    | Var of string 
    | Power of string * int 
    | Times of aexp list 
    | Sum of aexp list 

    let rec 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)) @ (h :: Times (diff (Times t, var))))   
     end 
    |Sum l -> 
     begin match l with 
      |h::t -> Sum (diff(h, var) :: diff(t, var)) 
     end 

此代码预计为工作如下:我有麻烦,在OCaml的制作差分功能(不是语法问题)

diff (Times[Const 2; Var "x"], "x") 

那么输出必须

Times[Const 2; Const 1] 

因为如果我们区分2倍,结果是2

但发生错误,它说:

File "", line 18, characters 20-25: 
Error: This variant expression is expected to have type 'a list 
     The constructor Times does not belong to type list 

为什么会发生此错误?我认为有些地方是错误的,但我找不到任何逻辑错误。

回答

1

让我们看看这个表情:

h :: Times (diff (Times t, var)) 

为简单起见,让我们代替diff (Times t, var),与dtdv,使我们有

h :: Times dtdv 

::缀构造要求,以左侧的表达式它的类型应该是'a,而右边的表达式应该有'a list的值。右边的表达式为Times dtdv,构造函数Times创建类型为aexp的值,而不是类型列表的值。

顺便说一句,你还有两个错误和两个更多的警告。这些错误是同一种类的,即,你想在需要列表的地方申请aexp类型的值,即,在这里:

Times (diff (h, var) :: t)) @ (h :: Times (diff (Times t, var)) 

让我们再次把它简化

Times (dhv::t) @ rest 

@运营商期望双方的列表,Times something,正如我们已经讨论过的,不是一个列表。

看起来,你很难通过大量的括号和优先规则。我讨厌括号。所以,我总是尝试使用let ... in谨慎,例如,让我们改写下面的表达式:

Sum ((Times (diff (h, var) :: t)) @ (h :: Times (diff (Times t, var)))) 

有了更加详细,但understanble版本:

let h' = diff (h,var) in 
let t' = diff (Times t,var) in 
let lhs = Times (h'::t) in 
let rhs = h :: Times t' in 
Sum ([email protected]) 

现在是更具可读性,而且你可以一一解决所有问题。另外,我建议不要试图解决大胖子功能中的所有问题,而是将事物分解为更易于处理的小函数,这也将解决您匹配内匹配的问题,例如,以下函数具有这样的结构,但更易于理解:

let rec 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) -> diff_power s i 
    |Times l -> diff_times l 
    |Sum l -> diff_sum l 
and diff_power s i = 
    if s = var then Times [Const i; Power (s, i - 1)] else Power (s, i) 
and diff_times l = match l with 
    |h::t -> Sum ((Times (diff (h, var) :: t)) @ (h :: Times (diff (Times t, var)))) 
and diff_sum l = match l with 
    |h::t -> Sum (diff(h, var) :: diff(t, var)) 
+0

谢谢你回答我。 我还在怀疑,我已经宣布Times - > aexp list ,我认为这意味着Times构造函数会生成aexp类型的列表。 我该如何解决这个问题..? –

+0

@송재민:'diff(Times t,var)'返回或返回产品总和。这是一个'aexp'结构'Sum',里面有addens列表。将'Times'构造函数应用于'Sum'结构似乎是不合情理的。正确的结果应该像'diff(Times [u,v,w],x)= Sum [Times [u',v,w],Times [u,Sum [Times [v',w]五,总和[时报[W']]]]]]'。理想情况下,单元素和产品是解压缩的... – LutzL

2

一些数学注释:

  • 变量不x的由可变x的导数是零,而不是原来的变量。

  • 对于不是x的变量的幂的相同,它也是相对于x的常数。

  • 为什么只有变量的权力,(a+b)^i是不可能的。更一般的情况就像特例一样容易。

对于产品的衍生物考虑三个因素,并且包括第一递归步骤分割uv*w

(u*v*w)' = u'*v*w + u*(v'*w+v*w') 

在前缀符号这可以写为

diff(*[u,v,w])=+[*[u',v,w],*[u,+[*[v',w],*[v,w']]]] 

这应该反映在类似

|h::t -> Sum ((Times (diff (h, var) :: t)) @ (Times (h :: (diff (Times t, var))))) 

由于两个元素的列表,可这也可以写成

|h::t -> Sum (Times (diff (h, var) :: t) , Times (h ,diff (Times t, var)))