5

Osiągam niewielki sukces, owijając głowę podstawowymi instalacjami typów z pakietu ad. Na przykład, następujący działa perfekcyjnie:Dopuszczalne typy w funkcjach 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] 

gdzie grad ma typ:

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

Gdybym zmienić podpis typu z ex do [Double] -> Double i spróbuj to samo, mam

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 

To samo zachowanie występuje podczas zastępowania Double konstruktorem pozornie dowolnego typu z rodzajem *, która tworzy instancję Num.

Gdy Traversable f jest na liście, pierwszy argument grad musi typu [AD s a] -> AD s a przez pewien dopuszczalny Mode - przykład Reverse. Ale oczywiście użytkownik grad nie musi zajmować się bezpośrednio konstruktorem AD lub . Zaglądanie do tych wewnętrznych elementów pozostawiło mnie trochę zagubionego; w szczególności nie mogę podążać ścieżką rodzaju/typu do różnicy między używaniem Num a => [a] -> a i [Double] -> Double.

Dlaczego podpis typu [Double] -> Double powoduje problemy z grad? A jeśli chodzi o zwykłe stare wykorzystanie biblioteki: czy jest jakiś sposób na użycie wersji [Double] -> Doubleex, czy jest to wersja polimorficzna?

(tytuł zainspirowany this similar question)

Odpowiedz

6

nie wiem bibliotekę ad, ale ponieważ grad spodziewa funkcję typu [AD s a] -> AD s a jako pierwszy parametr, nie można oczekiwać, aby być w stanie przekazać mu funkcję typu [Double] -> Double, ponieważ Double i AD są całkowicie różnymi typami.

Ogólny funkcja z Num przymusu działa, ponieważ AD sam w sobie jest również instancją Num, dlatego w swoim przykładzie roboczym ex dostaje specjalizuje się czegoś jak

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

Jeśli chcesz się specjalizować ex do obliczeń z wykorzystaniem Podwajasz, musisz nadać mu podpis, taki jak

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

Ahhhh ok, więc 'AD' jest instancją' Num'. Nie zauważyłem tego na liście instancji, ale widzę to teraz. – jtobin

+2

Ponadto, jeśli masz jakieś stałe leżące wokół jako Doubles, powiedzmy, w innych strukturach danych, być może będziesz musiał użyć Numeric.AD.Types.lift lub innych kombinatorów w Trybie, aby mieć interakcję z Twoimi AD Podwójne argumenty i wynik . –