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
此代码预计可以如下工作:
diff (Times[Const 2; Var "x"], "x")
然后输出必须
Times[Const 2; Const 1]
因为如果我们区分2x,结果就是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
为什么会出现这种错误?我认为有些地方是错的,但我找不到任何逻辑错误。
答案 0 :(得分:2)
一些数学笔记:
变量x
不是x
的变量的导数为零,而不是原始变量。
对于不是x
的变量的幂,它也是相对于x
的常量。
为什么只能使用变量(a+b)^i
。更一般的情况就像特殊情况一样简单。
对于产品的衍生产品,考虑三个因素,并包括第一个递归步骤拆分u
和v*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)))
答案 1 :(得分: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))))
有一个更详细但不易讨厌的版本:
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 (lhs@rhs)
现在它更具可读性,您可以逐一解决所有问题。
另外,我建议不要尝试解决大胖函数中的所有问题,而是将事物分成更容易处理的小函数,这也可以解决匹配中匹配问题例如,以下函数的结构更容易理解:
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))