5

我幾乎沒有成功地圍繞ad包中涉及的基本管道類型進行操作。例如,下面的工作完美:Numeric.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第一個參數必須有類型[AD s a] -> AD s a一段可接受Mode - 例如,Reverse。但很明顯,grad的用戶不必直接處理AD構造函數或Mode。偷看到這些內部結構讓我有點困惑;具體來說,我不能按照類型跟蹤使用Num a => [a] -> a[Double] -> Double之間的差異。

爲什麼類型簽名[Double] -> Double導致grad問題?而對於普通舊圖書館的使用:有沒有什麼辦法可以使用ex[Double] -> Double版本,或者是一個多態版本所必需的?

(稱號this similar question啓發)

回答

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進行計算雙打,你需要給它一個簽名,如

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

啊,好吧,所以'AD'是'Num'的一個實例。我沒有注意到,在實例列表中,但我現在看到它。 – jtobin 2012-07-25 19:56:36

+2

另外,如果你有一些常量在雙精度上,比如說在其他數據結構中,你可能需要使用Numeric.AD.Types.lift或Mode中的其他combinators讓它們與AD進行交互。雙參數和結果。 – 2012-07-28 09:23:33

相關問題