可接受的类型Numeric.AD 功能
-
11-12-2019 - |
题
我几乎没有成功地将我的头围绕在涉及的类型的基本管道上。 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
, ,自 Double
和 AD
是完全不同的类型。
通用函数 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