Допустимые типы в функциях Numeric.AD

У меня мало успехов в том, чтобы разобраться в основной сантехнике типов, включенных в пакет 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? И с точки зрения использования старой простой библиотеки :, есть ли способ использовать [Double] -> Doubleверсию exили необходима полиморфная версия?

(название, вдохновленное похожим вопросом)

5
задан Community 23 May 2017 в 12:01
поделиться