Reify the (compiled) code to its typed TH representation (or, the dictionary *view*, to be precise) and reflect/compile that code. We must spread the code through several modules, due to the particular requirement of the Template Haskell. See DiffTest.hs for reflection of the differentiated TH code back into (machine) code.
- testf1 :: Num a => a
- diffC :: (Floating a, Floating b) => Var b -> Code a -> Code a
- simpleC :: Floating a => Var b -> Code a -> Code a
- simpleCL :: Floating a => Var b -> Code a -> Maybe (Code a)
- diff_fn :: Floating b => (forall a. Floating a => a -> a) -> QCode (b -> b)
- show_fn :: (forall a. Floating a => a -> a) -> IO ()
We can define a function
we can even compile it. At any point, we can reify it, into a `dictionary view' The result is the TH code, which we can print, and compile back to the code. We can also differentiate the TH code, simplify it, partially evaluate it, etc.
Symbolic Differentiation of the reified, typed TH code expressions The derivative over the code is a type preserving operation
Simplification rules simplification is type-preserving obviously, simplification is an `open-ended' problem: we could even recognize common sub-expressions and simplify them by introducing let binding. In the following however, we do trivial simplification only. One can always add more simplification rules later.
repeat until no simplifications are made
And that's about it. Putting it all together gives us: