Следуя терминологии из этой превосходной серии , давайте представим такое выражение, как (1 + x^2 - 3x)^3
через Term Expr
, где типы данных следующие:
data Expr a =
Var
| Const Int
| Plus a a
| Mul a a
| Pow a Int
deriving (Functor, Show, Eq)
data Term f = In { out :: f (Term f) }
Есть лисхема рекурсии, подходящая для выполнения символьного дифференцирования?Я чувствую, что это почти футуморфизм, специализированный на Term Expr
, то есть futu deriveFutu
для соответствующей функции deriveFutu
:
data CoAttr f a
= Automatic a
| Manual (f (CoAttr f a))
futu :: Functor f => (a -> f (CoAttr f a)) -> a -> Term f
futu f = In <<< fmap worker <<< f where
worker (Automatic a) = futu f a
worker (Manual g) = In (fmap worker g)
Это выглядит довольно хорошо, за исключением того, что вместо подчеркнутых переменных Term
sиз CoAttr
s:
deriveFutu :: Term Expr -> Expr (CoAttr Expr (Term Expr))
deriveFutu (In (Var)) = (Const 1)
deriveFutu (In (Const _)) = (Const 0)
deriveFutu (In (Plus x y)) = (Plus (Automatic x) (Automatic y))
deriveFutu (In (Mul x y)) = (Plus (Manual (Mul (Automatic x) (Manual _y)))
(Manual (Mul (Manual _x) (Automatic y)))
)
deriveFutu (In (Pow x c)) = (Mul (Manual (Const c)) (Manual (Mul (Manual (Pow _x (c-1))) (Automatic x))))
Версия без рекурсивных схем выглядит следующим образом:
derive :: Term Expr -> Term Expr
derive (In (Var)) = In (Const 1)
derive (In (Const _)) = In (Const 0)
derive (In (Plus x y)) = In (Plus (derive x) (derive y))
derive (In (Mul x y)) = In (Plus (In (Mul (derive x) y)) (In (Mul x (derive y))))
derive (In (Pow x c)) = In (Mul (In (Const c)) (In (Mul (In (Pow x (c-1))) (derive x))))
В качестве дополнения к этому вопросу, существует ли рекурсивная схема для дифференциации и исключения "пустые "Expr
s, такие как Plus (Const 0) x
, которые возникают в результате дифференциации - за один проход по данным?