14

I am working with Haskell for quite a while now, but I am far from being an expert. But I see that the functional approach to programming suits me the best.

So far I am working on a project to calculate some serious stuff, like currents and potentials radiated from a given structure.

I followed the blog written by Conal Elliott (here is some more Linear Maps) which is very nice and fundamental.

Unfortunately, I am lacking a simple example :)

To be more precise, I have a curve

f:[0,1] in R -> R³
t -> a*e_y + 2*t*e_z

which is a simple straight line at (0,a,2*t). When I want to calculate the derivative of f, e.g. for the length of the curve, I know the mathematical result, which is quite simple (0,0,2), but how do I accomplish this in Haskell, especially with the vector-space package?

I really want to use this library because of its functionality, it is exactly the approach I would have take too (but I am not that far ahead on the Haskell road)

What I have so far is this:

{-# LANGUAGE Rank2Types, TypeOperators, FlexibleContexts, TypeFamilies #-}
{-# OPTIONS_GHC -Wall #-}
import Numeric.GSL.Integration
import Data.VectorSpace
import Data.Basis
import Data.Cross
import Data.Derivative
import Data.LinearMap

type Vec3 s = Three s

prec :: Double
prec = 1E-9

f1 :: (Floating s, VectorSpace s, Scalar s ~ s) => s -> s
f1 = id

c1 :: Double -> Vec3 Double
c1  = \t -> linearCombo [((v 0 0 1),f1 t),(( v 0 1 0),2)]

derivC :: Double -> Vec3 (Double :> Double)
derivC t = c1 (pureD t)

It is the the actual implementation of the pureD function, so far nothing that I have tried works to get this snippet to compile. I get the following error:

tests.hs:26:12:
   Couldn't match expected type `Double :> Double'
               with actual type `Double'
   Expected type: Vec3 (Double :> Double)
     Actual type: Vec3 Double
   In the return type of a call of `c1'
   In the expression: c1 (pureD t)
Failed, modules loaded: none.

There is also a graphics library which uses vector-space and there is even an example on a torus, where pureD is used. I tried to deduce the example but I don't see how I can map it to my problem.

Any help would be greatly appreciated.

Thanks in advance

PS: I cannot post all the links I'd like to, but am willing to provide

Community
  • 1
  • 1
TheMADMAN
  • 319
  • 2
  • 8
  • Well - I don't know much about these libraries, but the types don't match. `pureD :: (LMapDom a s, VectorSpace b s) => b -> a :> b` So the type of `pureD t` is `Double :> Double` but c1 expects an argument of `Double`. (Which is what the error says) – Oliver Feb 17 '12 at 09:23
  • 1
    Thx Oliver, I have seen this too, but I had already posted the question. The thing is, still, that I am not clear with the actual derivation, that means how do I change my function to match with the type signature. I will take a closer look at mnish's answer. – TheMADMAN Feb 18 '12 at 11:50

2 Answers2

5

That's an interesting library.. Thanks for sharing. Although I don't understand the concept of the library yet, how about this code:

{-# LANGUAGE Rank2Types, TypeOperators, FlexibleContexts, TypeFamilies #-}
module Main where

import Data.LinearMap
import Data.Maclaurin

diff :: (Double :~> (Double,Double,Double) ) -> (Double :~> (Double,Double,Double))
diff f = \x ->  (atBasis (derivative  (f x)) ())

eval :: (Double :~> (Double,Double,Double)) -> Double -> (Double,Double,Double)
eval f x = powVal (f x)        

f :: Double :~> (Double,Double,Double)
f x = tripleD (pureD 0,pureD 1,(2*idD) x)


*Main> map (eval f) [0,0.2 .. 1]
[(0.0,1.0,0.0),(0.0,1.0,0.4),(0.0,1.0,0.8),(0.0,1.0,1.2000000000000002),
 (0.0,1.0,1.6000000000000003),(0.0,1.0,2.0000000000000004)]

*Main> map (eval (diff f)) [0,0.2 .. 1]
[(0.0,0.0,2.0),(0.0,0.0,2.0),(0.0,0.0,2.0),(0.0,0.0,2.0),(0.0,0.0,2.0), 
 (0.0,0.0,2.0)]

*Main> map (eval (diff $ diff f)) [0,0.2 .. 1]
 [(0.0,0.0,0.0),(0.0,0.0,0.0),(0.0,0.0,0.0),(0.0,0.0,0.0),(0.0,0.0,0.0),(0.0,0.0,0.0)]

Try also g x = tripleD (pureD 0,idD x,(idD*idD) x) (which seem to represent the curve (0,x,x^2)).

mnish
  • 1,869
  • 1
  • 13
  • 15
  • 1
    Well, that looks very good, thank you! When I understand this correctly, I define my function of type :~>, which means it is indefinitely derivable, makes sense, because that should be the case. I also understand the meaning of "derivation variable",now. The eval function is needed to extract the value at point. The function idD means that a derivation at this place may occur. How does "diff" work? I think I misunderstand the meaning of basis, a basis in R³ is e.g. ((1,0,0),(0,1,0),(0,0,1)), but that is not what the library means. In any case, u have helped me a lot! thanks again – TheMADMAN Feb 18 '12 at 12:12
  • 1
    You are welcome. It seems to me that the 'basis' represents the basis of the tangent space, which is Double in this case. It is represented as () because it is one-dimensional. If the tangent space is two dimensional, the 'basis' is represented by Either () () ,the two point space. – mnish Feb 18 '12 at 16:25
  • Ok, this is clear now. I am able to dig deaper into the library now and apply it to my needs. When I have further questions I know who to ask :) – TheMADMAN Feb 18 '12 at 17:05
0

You might want to try the ad package, which does its best to make it easy to do automatic differentiation of functions written in transparent idiomatic Haskell.

$ cabal install ad
$ ghci
Prelude> :m + Numeric.AD
Prelude Numeric.AD> diffF (\t->let a=3 in [0,a,2*t]) 7
[0,0,2]
Prelude Numeric.AD> let f t = let a=3 in [0,a,2*t]
Prelude Numeric.AD> diffF f 17
[0,0,2]