5

围绕包装中涉及的类型的基本管道,我几乎没有成功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如果我更改to的类型签名[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直接处理。窥视这些内部结构让我有点困惑。具体来说,我无法按照种类/类型追踪来区分 usingNum a => [a] -> a[Double] -> Double.

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

(标题受这个类似问题的启发)

4

1 回答 1

6

我不知道这个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使用 Doubles 进行计算,您需要给它一个签名,例如

ex :: Mode s => [AD s Double] -> AD s Double
于 2012-07-25T18:32:01.790 回答