#haskell #types #automatic-differentiation
#haskell #типы #автоматическое дифференцирование
Вопрос:
Я пытаюсь работать с числовым.AD и пользовательский тип выражения. Я хочу вычислить символический градиент введенного пользователем выражения. Первая попытка с постоянным выражением работает хорошо:
calcGrad0 :: [Expr Double]
calcGrad0 = grad df vars
where
df [x,y] = eval (env [x,y]) (EVar "x"*EVar "y")
env vs = zip varNames vs
varNames = ["x","y"]
vars = map EVar varNames
Это работает:
>calcGrad0
[Const 0.0 : (Const 0.0 : (EVar "y" :* Const 1.0)),Const 0.0 : (Const 0.0 : (EVar "x" :* Const 1.0))]
Однако, если я извлеку выражение в качестве параметра:
calcGrad1 :: [Expr Double]
calcGrad1 = calcGrad1' (EVar "x"*EVar "y")
calcGrad1' e = grad df vars
where
df [x,y] = eval (env [x,y]) e
env vs = zip varNames vs
varNames = ["x","y"]
vars = map EVar varNames
Я получаю
Could not deduce (a ~ AD s (Expr a1))
from the context (Num a1, Floating a)
bound by the inferred type of
calcGrad1' :: (Num a1, Floating a) => Expr a -> [Expr a1]
at Symbolics.hs:(60,1)-(65,29)
or from (Mode s)
bound by a type expected by the context:
Mode s => [AD s (Expr a1)] -> AD s (Expr a1)
at Symbolics.hs:60:16-27
`a' is a rigid type variable bound by
the inferred type of
calcGrad1' :: (Num a1, Floating a) => Expr a -> [Expr a1]
at Symbolics.hs:60:1
Expected type: [AD s (Expr a1)] -> AD s (Expr a1)
Actual type: [a] -> a
In the first argument of `grad', namely `df'
In the expression: grad df vars
Как мне заставить ghc принять это?
Комментарии:
1. Это уже было решено Сайзаном в #haskell. Мне просто не хватало fmap lift e при вызове eval.
Ответ №1:
Я предполагаю, что вы забываете применить lift для преобразования Expr
в AD s Expr
.
Если вы заинтересованы в использовании пакета ad для символьного дифференцирования. Отслеживаемый пакет Леннарта Аугустссона работает хорошо.
Ответ №2:
Когда GHC не может вывести сигнатуру равенства типов для допустимой функции, как в вашем случае, решение состоит в том, чтобы присвоить функции сигнатуру типа. Я не знаю интерфейс к этой библиотеке. Однако, я предполагаю, что правильная подпись является calcGrad1 :: (Num a, Floating a) => Expr a -> [Expr a]
.