[Haskell-beginners] Simple Math Function

Daniel Fischer daniel.is.fischer at web.de
Fri Sep 10 13:45:41 EDT 2010


On Friday 10 September 2010 18:35:45, Lorenzo Isella wrote:
> Dear All,
> I am trying to translate some codes of mine into haskell. It looks like
> Haskell can shorten quite a bit the implementation of mathematical
> formulas. Let us say you have two list of real numbers; let us call them
> y and t. The list t is increasing (a sort of time).
> Now consider the couples (t_a, y_a) and (t_b,y_b) where
> t_a<t_b i.e.  two (non-simultaneous) values of t and the corresponding
> y_a and y_b. There are no assumptions on y.
> What I would like to write is a function which checks the existence
> (t_c,y_c), where y_a<y_c<y_b (i.e. y_c is some intermediate time) such
> that

I suppose that should've been t_a < t_c < t_b since you speak of times.

>
> y_c<y_b+(y_a-y_b)*(t_b-t_c)/(t_b-t_a).
>
> I have already implemented this in other languages, but I ended up with
> quite lengthy functions (what if a list is empty, what if it has fewer
> than 2-3 elements and so on...).
> Also, it would be nice to iterate this function on all possible
> combinations (t_a, y_a) and (t_b,y_b), t_a<t_b I can form from my data.
> I am not asking someone to 'do my homework', rather I would like to see
> how much more compact things can get in haskell.
> Many thanks
>
> Lorenzo

-- Event has time and value, probably some other name would be more 
appropriate
type Event = (Double, Double)


combinations :: (Event -> Event -> Event -> Bool) -> [Event]
             -> [((Event, Event), [Event])]
combinations _ [] = []
combinations cond (e:es) = sat e [] es ++ combinations cond es
  where
    sat _ _ [] = []
    sat start between (now : later) = 
        ((start, now), filter (cond start now) between)
          : sat start (now : between) later

gives you a list of all pairs of events together with all intermediate 
events satisfying the condition.
To check whether for a pair of events there are any intermediate events 
satisfying the condition, use (not . null . snd). To find out how many, 
(length . snd).

If you have many events, however, using a list would probably be too 
inefficient, then instead of a [(Double, Double)], you'd better use a
Data.Map.Map Double Double
(or use a newtype for the time if you calculate the times in different 
ways, in floating point math, sin (2*x) == 2 * sin x * cos x isn't always 
true).



More information about the Beginners mailing list