5

Sto riscuotendo un piccolo successo intorno alla tubatura di base dei tipi coinvolti nel pacchetto ad. Ad esempio, il seguente funziona perfettamente:Tipi accettabili nelle funzioni 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] 

dove grad ha il tipo:

grad 
    :: (Num a, Traversable f) => 
    (forall (s :: * -> *). Mode s => f (AD s a) -> AD s a) 
    -> f a -> f a 

Se cambio la firma tipo di ex-[Double] -> Double e provo la stessa cosa, ottengo

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 

Lo stesso comportamento si verifica quando si sostituisce Double con apparentemente qualsiasi tipo di costruttore con tipo * che crea un'istanza Num.

Quando il Traversable f è un elenco, il primo argomento di grad deve avere tipo [AD s a] -> AD s a per qualche accettabile Mode - esempio Reverse. Ma chiaramente l'utente di grad non ha a che fare direttamente con il costruttore AD o con lo Mode. Sbirciando in questi interni mi ha lasciato un po 'confuso; nello specifico, non posso seguire il tipo/tipo di traccia per la differenza tra l'utilizzo di Num a => [a] -> a e [Double] -> Double.

Perché la firma del tipo [Double] -> Double causa problemi con grad? E in termini di semplice utilizzo della vecchia libreria: esiste un modo per utilizzare la versione [Double] -> Double di ex oppure è necessaria una versione polimorfa?

(titolo ispirato this similar question)

risposta

6

non so la biblioteca ad, ma dal momento che grad aspetta una funzione di tipo [AD s a] -> AD s a come primo parametro, non si può pretendere di essere in grado di passare una funzione di tipo [Double] -> Double, dal Double e AD sono tipi completamente diversi.

La funzione generica con Num vincolo funziona, perché AD stesso è anche un esempio di Num, quindi, nel tuo esempio di lavoro, ex ottiene specializzato in qualcosa di simile

ex :: (Mode s, Fractional a) => [AD s a] -> AD s a 

Se si desidera specializzarsi ex per i calcoli utilizzando Doppio, è necessario dargli una firma come

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

Ahhhh ok, quindi 'AD' è un'istanza di' Num'. Non l'ho notato nella lista delle istanze, ma ora lo vedo. – jtobin

+2

Inoltre, se alcune costanti si trovano in posizione doppia, ad esempio in altre strutture di dati, potrebbe essere necessario utilizzare Numeric.AD.Types.lift o gli altri combinatori in modalità per fare in modo che interagiscano con gli argomenti di annuncio Double Argomenti e risultato . –