Akzeptable Typen in Numeric.AD funktionen
-
11-12-2019 - |
Frage
Ich habe wenig Erfolg damit, meinen Kopf um die grundlegenden Klempnerarbeiten der Typen zu wickeln, die an der ad
Paket.Zum Beispiel funktioniert Folgendes perfekt:
import Numeric.AD
ex :: Num a => [a] -> a
ex [x, y] = x + 2*y
> grad ex [1.0, 1.0]
[1.0, 2.0]
wo grad
hat den Typ:
grad
:: (Num a, Traversable f) =>
(forall (s :: * -> *). Mode s => f (AD s a) -> AD s a)
-> f a -> f a
Wenn ich die Typensignatur von ändere ex
zu [Double] -> Double
und versuche das gleiche, ich verstehe
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
Das gleiche Verhalten tritt beim Ersetzen auf Double
mit scheinbar jedem Typkonstruktor mit Art *
das instanziiert Num
.
Wenn der Traversable f
ist eine Liste, das erste Argument von grad
muss Typ haben [AD s a] -> AD s a
für einige akzeptabel Mode
- beispielsweise., Reverse
.Aber eindeutig der Benutzer von grad
muss sich nicht mit dem beschäftigen AD
konstruktor oder der Mode
direkt.Ein Blick in diese Interna hat mich etwas verwirrt;insbesondere kann ich der Art / Typ-Spur nicht zum Unterschied zwischen der Verwendung folgen Num a => [a] -> a
und [Double] -> Double
.
Warum funktioniert die Typensignatur [Double] -> Double
probleme verursachen mit grad
?Und in Bezug auf die einfache alte Bibliotheksnutzung:gibt es eine Möglichkeit, das zu verwenden [Double] -> Double
version von ex
, oder ist eine polymorphe Version notwendig?
(titel inspiriert von diese ähnliche Frage)
Lösung
Ich kenne das nicht ad
bibliothek, aber seit grad
erwartet eine Funktion vom Typ [AD s a] -> AD s a
als erster Parameter können Sie nicht erwarten, dass ihm eine Funktion vom Typ übergeben werden kann [Double] -> Double
, da Double
und AD
sind völlig verschiedene Typen.
Die generische Funktion mit Num
einschränkung funktioniert, weil AD
selbst ist auch eine Instanz von Num
, also in Ihrem Arbeitsbeispiel, ex
wird spezialisiert auf so etwas wie
ex :: (Mode s, Fractional a) => [AD s a] -> AD s a
Wenn Sie sich spezialisieren möchten ex
für Berechnungen mit Doppelwerten müssen Sie ihm eine Signatur geben, z
ex :: Mode s => [AD s Double] -> AD s Double