我几乎没有成功地将我的头围绕在涉及的类型的基本管道上。 ad 包裹。例如,以下内容完美地工作:

import Numeric.AD

ex :: Num a => [a] -> a
ex [x, y] = x + 2*y

> grad ex [1.0, 1.0]
[1.0, 2.0]

哪里 grad 有类型:

grad
  :: (Num a, Traversable f) =>
     (forall (s :: * -> *). Mode s => f (AD s a) -> AD s a)
     -> f a -> f a

如果我改变的类型签名 ex[Double] -> Double 尝试同样的事情,我得到

Couldn't match expected type `AD s a0' with actual type `Double'
Expected type: f0 (AD s a0) -> AD s a0
  Actual type: [Double] -> Double

更换时会发生相同的行为 Double 与看似任何类型构造函数与kind * 实例化 Num.

Traversable f 是一个列表,第一个参数 grad 必须有类型 [AD s a] -> AD s a 对于一些可以接受的 Mode -例如, Reverse.但显然是 grad 不需要处理 AD 构造函数或 Mode 直接。偷看这些内部的东西让我有点困惑;具体来说,我无法按照类型/类型跟踪到使用之间的区别 Num a => [a] -> a[Double] -> Double.

为什么类型签名 [Double] -> Double 导致问题与 grad?就普通的旧图书馆使用而言:有什么办法可以使用 [Double] -> Double 版本的 ex, ,还是多态版本是必要的?

(标题灵感来自 这个类似的问题)

有帮助吗?

解决方案

我也不知道 ad 库,但自 grad 期望类型的函数 [AD s a] -> AD s a 作为它的第一个参数,你不能期望能够传递一个类型的函数 [Double] -> Double, ,自 DoubleAD 是完全不同的类型。

通用函数 Num 约束起作用,因为 AD 本身也是一个实例 Num, ,因此在你的工作例子中, ex 专门从事类似的事情

ex :: (Mode s, Fractional a) => [AD s a] -> AD s a

如果你想专攻 ex 对于使用双打的计算,您需要给它一个签名,例如

ex :: Mode s => [AD s Double] -> AD s Double
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top