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

jto*_*bin 5 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]
Run Code Online (Sandbox Code Playgroud)

哪里grad有类型:

grad
  :: (Num a, Traversable f) =>
     (forall (s :: * -> *). Mode s => f (AD s a) -> AD s a)
     -> f a -> f a
Run Code Online (Sandbox Code Playgroud)

如果我改变的类型签名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
Run Code Online (Sandbox Code Playgroud)

当用实例化的Double类替换看似任何类型的构造函数时,会发生相同的行为. *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,或者是必需的多态版本?

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

sha*_*ang 6

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

带有Num约束的泛型函数起作用,因为AD它本身也是一个实例Num,因此在你的工作示例中,它ex专门用于类似的东西

ex :: (Mode s, Fractional a) => [AD s a] -> AD s a
Run Code Online (Sandbox Code Playgroud)

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

ex :: Mode s => [AD s Double] -> AD s Double
Run Code Online (Sandbox Code Playgroud)

  • 此外,如果你有一些常量作为双打,比如说,在其他数据结构中,你可能需要使用Numeric.AD.Types.lift或模式中的其他组合器让它们与你的AD的双参数和结果进行交互. (2认同)