[Haskell-beginners] numerical integration over lists

Daniel Fischer daniel.is.fischer at googlemail.com
Sun Feb 5 17:28:22 CET 2012


On Sunday 05 February 2012, 16:56:50, Thomas Engel wrote:
> Hello Henk-Jan,
> 
> > The line
> > 
> > >integriereListe [][]  = [0.0]
> > 
> > should be
> > 
> > >integriereListe [][]  = 0.0
> > 
> > as the line below that calculates a number, not a list of numbers
> > (that is, the type is different for that line).
> 
> thanks for the hint. I have changed the function accordingly but there
> is still an error for the types.
> 
> integriereListe::(Float)->(Float)->(Float)

The type (Float) is just the type Float, the parentheses do nothing here. 
What you want the arguments to be is _lists of Float_, that is: [Float].
Now the question is whether you want the result to be a single number or a 
list, so the type should be one of

integriereListe :: [Float] -> [Float] -> Float

or

integriereListe :: [Float] -> [Float] -> [Float]


> integriereListe [][]  = 0.0

If you want a list as result, that should become [0.0].

> integriereListe (x:xs) (y:ys)   = (y - y2) /2 * (x2 -x)
>                                  where
>                                  x2 = head xs
>                                  y2 = head ys

Note that this will lead to an error call if eitherof the passed lists has 
only one element. Also your function definition doesn't treat the case that 
only one of the two arguments is nonempty.

> 
>  Couldn't match expected type `Float' with actual type `[t0]'
>     In the pattern: x : xs
>     In an equation for `integriereListe':
>         integriereListe (x : xs) (y : ys)
>           = (y - y2) / 2 * (x2 - x)

Should that be (y+y2)/2 ?

>           where
>               x2 = head xs
>               y2 = head ys
> 
> This are my first steps in haskell. I don't know whether my first basic
> approach is OK or is there a better solution for this calculation?
> There is no formula to map over a list and integrate, I only have two
> list with values. I can zip the lists together to have a list of tuples
> if this is an advantage. What I need is the first and the second value
> from each list, do the calculation, the second value will become the
> first value of the next calculation and so on until the end of the
> lists. I also need the result of the last calculation to add to the
> current calculation.

If I understand correctly, use

zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]

-- calculates the list of differences between successive elements,
-- differences [x1,x2,x3,...] = [x2-x1, x3-x2, ...]
--
-- We use subtract and don't swap the list arguments to zipWith
-- becuase this way there is no need to handle an empty list
-- specially, zipWith's definition lets (tail xs) unevaluated in that case.
--
differences :: Num a => [a] -> [a]
differences xs = zipWith subtract xs (tail xs)

areas :: Floating a => [a] -> [a] -> [a]
areas xs ys
    = zipWith (\dx dy -> dx * dy/2) (differences xs) (differences ys)

-- if it should have been (y+y2)/2 above, make that
-- sums ys, where sums ks = zipWith (+) ks
-- or areas xs ys = zipWith (*) (differenses xs) (means ys)
-- where means zs = map (/ 2) (sums zs)

and now, if you only wan the total,

area xs ys = sum (areas xs ys)

and if you want running sums

integrals xs ys = scanl (+) 0 (areas xs ys)

> 
> My calculation in excel with VBA is working, but it's quite difficult
> for me to do this with functional programming.
> 
> Any hints are welcome!
> 
> Thomas



More information about the Beginners mailing list