Types acceptables dans les fonctions Numeric.AD
-
11-12-2019 - |
Question
J'ai peu de succès à comprendre la plomberie de base des types impliqués dans le ad
emballer.Par exemple, ce qui suit fonctionne parfaitement :
import Numeric.AD
ex :: Num a => [a] -> a
ex [x, y] = x + 2*y
> grad ex [1.0, 1.0]
[1.0, 2.0]
où grad
a le type :
grad
:: (Num a, Traversable f) =>
(forall (s :: * -> *). Mode s => f (AD s a) -> AD s a)
-> f a -> f a
Si je change la signature de type de ex
à [Double] -> Double
et j'essaye la même chose, j'obtiens
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
Le même comportement se produit lors du remplacement Double
avec apparemment n'importe quel constructeur de type avec type *
qui instancie Num
.
Quand le Traversable f
est une liste, le premier argument de grad
doit avoir le type [AD s a] -> AD s a
pour certains acceptable Mode
- par exemple., Reverse
.Mais il est clair que l'utilisateur de grad
n'a pas à s'occuper du AD
constructeur ou le Mode
directement.Jeter un coup d’œil à ces éléments internes m’a laissé un peu confus ;plus précisément, je ne peux pas suivre la piste genre/type jusqu'à la différence entre l'utilisation Num a => [a] -> a
et [Double] -> Double
.
Pourquoi la signature de type [Double] -> Double
causer des problèmes avec grad
?Et en termes d'utilisation simple de la vieille bibliothèque :est-il possible d'utiliser le [Double] -> Double
version de ex
, ou une version polymorphe est-elle nécessaire ?
(titre inspiré de cette question similaire)
La solution
je ne connais pas le ad
bibliothèque, mais depuis grad
attend une fonction de type [AD s a] -> AD s a
comme premier paramètre, vous ne pouvez pas vous attendre à pouvoir lui passer une fonction de type [Double] -> Double
, depuis Double
et AD
sont des types complètement différents.
La fonction générique avec Num
la contrainte fonctionne, car AD
lui-même est également un exemple de Num
, donc dans votre exemple de travail, ex
se spécialise dans quelque chose comme
ex :: (Mode s, Fractional a) => [AD s a] -> AD s a
Si vous souhaitez vous spécialiser ex
pour les calculs utilisant Doubles, vous devez lui donner une signature telle que
ex :: Mode s => [AD s Double] -> AD s Double