Numeric.AD函数中可接受的类型

时间:2012-07-25 16:16:20

标签: haskell types automatic-differentiation constraint-kinds

我几乎没有成功地绕着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替换为具有实例化*的类型Num的任何类型构造函数时,会发生相同的行为。

Traversable f是列表时,grad的第一个参数必须为某些可接受的Mode类型[AD s a] -> AD s a - 例如Reverse。但很明显grad的用户无需直接处理AD构造函数或Mode。窥视这些内部结构让我有些困惑;具体来说,我无法遵循使用Num a => [a] -> a[Double] -> Double之间的差异/类型跟踪。

为什么类型签名[Double] -> Double会导致grad出现问题?就简单的旧库使用而言:有没有办法使用[Double] -> Double ex版本,或者是必需的多态版本?

(标题灵感来自this similar question

1 个答案:

答案 0 :(得分:6)

我不知道ad库,但由于grad期望类型为[AD s a] -> AD s a的函数作为其第一个参数,因此您不能指望将其传递给它类型为[Double] -> Double的函数,因为DoubleAD是完全不同的类型。

Num约束的泛型函数有效,因为AD本身也是Num的一个实例,因此在您的工作示例中,ex专门用于类似< / p>

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

如果你想使用双打专门化ex进行计算,你需要给它一个签名,例如

ex :: Mode s => [AD s Double] -> AD s Double