In response to
clamp, a commenter unerringly pointed out another function whose common name I didn't know:
lerp, for linear interpolation. You know the operation - you have two points and you want a line:
lerp :: (Num a, Num b) ⇒ (a, b) → (a, b) → a → b lerp (x1,y1) (x2,y2) x = y1 + (x - x1) * (y2 - y1) / (x2 - x1)?
foo = lerp (1,1) (10,4)?
foo 42 ?
What if you have more than two points? The obvious generalization is to interpolate between successive pairs of points:
polylerp :: (Num a, Num b) ⇒ [(a, b)] → a → b polylerp  _ = error "domain" polylerp ((x1, _):ps) x | x1 > x = error "domain" polylerp ((x1, y1):ps) x | x1 == x = y1 polylerp ((x1, y1):(x2, y2):_) x | x2 > x = lerp (x1, y1) (x2, y2) x polylerp (_:ps) x = polylerp ps x
(Apologies for the explicit recursion. I wanted to write this with combinators to more closely resemble the natural-language description, but even with made-to-order combinators, I can't find anything clearer. This sort of iteration - a fold that operates on more than one element at once - is often awkward to express.)
The commenter mentioned that
clamp, is used a lot in graphics. This use is more specific than interpolating arbitrary functions between points: it's used to mix two pixels, for applications like antialiasing or transparency. This doesn't require arbitrary X-coordinates, so a simpler variant of
lerp is common:
lerp :: (Num a, Num b) ⇒ b → b → a → b lerp y1 y2 s = y1 + s * (y2 - y1)
clamp, I've used this form of
lerp before, but didn't know its standard name - I called it
mix. Can you tell I'm not a graphics person?
Now for a question. The examples above are in (untested) Haskell, but the type signatures are not the real ones, since Haskell requires in all of them that
a == b. I wrote them this way to make the distinction between X and Y coordinates clear, since the types would be unreadable otherwise. Is this a good idea?