At the end of the previous post I had intended this posting to be an exploration of a recursive definition of *Dual* that will give an infinite (lazy) list of derivatives. However, there’s still a lot to play with using our simple

data Dual a = Dual a a Let’s try a simple function of two variables…

and at we have

Now we can evaluate at using dual numbers with a subscript of x or y to ‘remember’ where it came from…i.e we want but really are the ‘same thing’.

Notice that the coefficients of are the same as the partial derivatives! This sort of suggests that we can get in isolation by setting . In effect setting is the equivalent of treating as constant and similarly for , which is how partial derivatives are calculated.

So let’s try this in Haskell…

1 2 3 4 5 6 7 8 9 10 11 12 |
-- The function λ-> f = \x y -> x^2 + x*y -- evaluate at (1,2) λ-> f 1 2 3 -- Try dual keeping y constant - to get partial dx λ-> f (Dual 1 1) (Dual 2 0) Dual 3 4 -- now x constant to get partial dy λ-> f (Dual 1 0) (Dual 2 1) Dual 3 1 |

as can be seen the partial derivatives simply drop out!

Extending to three variables and hiding the use of *Dual* we have

1 2 3 4 |
pDx, pDy, pDz :: (Num a) => (Dual a -> Dual a -> Dual a -> t) -> a -> a -> a -> t pDx f x y z = f (Dual x 1) (Dual y 0) (Dual z 0) pDy f x y z = f (Dual x 0) (Dual y 1) (Dual z 0) pDz f x y z = f (Dual x 0) (Dual y 0) (Dual z 1) |

Which leads to a neat Haskell function for the gradient operator

1 2 3 4 |
grad :: (Num a, Num a, Num a) => (Dual a -> Dual a-> Dual a -> Dual a) -> a -> a -> a -> (a, a, a) grad f x y z = (x', y', z' ) where Dual _ x' = pDx f x y z Dual _ y' = pDy f x y z Dual _ z' = pDz f x y z |

Actually if we import the *Vector* package, used in the series *‘Haskell, Vectors and Simple Mechanics*‘ then we can use ‘*Vector*‘ and write a ‘proper’ *grad* function:

1 2 |
gradV :: (Dual Scalar -> Dual Scalar -> Dual Scalar -> Dual Scalar) -> Scalar -> Scalar -> Scalar -> Vector gradV f x y z = V (grad f x y z) |

where we simply create a *Vector* from the result of applying the *grad* function – *gradV*. Using a Vector will then open it up to further vector-based manipulation…

For example, this is taken from ‘The Gradient and Directional Derivatives’

**Example**

What is the directional derivative in the direction <1,2> of the function z=f(x,y)=4x^2+y^2 at the point x=1 and y=1. The gradient is <8x,2y>, which is <8,2> at the point x=1 and y=1. The direction u is <2,1>. Converting this to a unit vector, we have <2,1>/sqrt(5). Hence,

And working the above out in *ghci* using our *gradV* and *Vector* package…

1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
-- The initial function λ-> f = \x y _ -> 4*x^2 + y^2 -- The direction u is <2,1> λ-> v = V (2, 1, 0) -- Converting this to a unit vector λ-> vn = normalise v -- dot product of gradV and vn λ-> (gradV f 1 1 0) >.< vn 8.049845 -- which is 18/(sqrt 5) :) |

So really this post was a bit of an aside to show how easily the use of *Dual* extends to functions of more than one variable and how the gradient operator can be easily defined. We then tied this into a simple example using *Vectors*. Next time we will look at extending the *Dual* idea to produce second and higher order derivatives and see where that takes us! As always the code is on Github.

Thanks for reading!