In Haskell, a list is just another data structure, perhaps with some (in my opinion) confusing notation. With any data structure, you can use pattern matching. When you're only working with lists, you have three possible things in a pattern:
- A variable, like
x.
- A constructor applied to zero or more patterns,
- like with
(:) x xs (or perhaps more familiarily: x:xs),
- or
[]
Note that, in patterns, you apply constructors to patterns. It's perfectly allowable to write (:) x ((:) y ys) (more commonly written as x:y:ys), which matches any list of at least two elements, and assigns the first element to x, the second to y, and the remainder of the list to ys.
The skeleton of your within function would look something like this:
theFunction theList = case theList of
x:y:ys -> if canGiveAnswer x y
then buildAnswer x y
else theFunction (y:ys)
Here, theFunction tries to match its input with the pattern x:y:ys, checks whether x and y are sufficient to give an answer, and do so when it can, or restart itself (theFunction (y:ys)) with the first element of the list removed.
You can write this more tersely like
theFunction (x:y:ys) = if canGiveAnswer x y then buildAnswer x y else theFunction (y:ys)
or even
theFunction (x:y:ys) | canGiveAnswer x y = buildAnswer x y
| True = theFunction (y:ys)
Of course, in your case, you need an extra argument:
within :: (Ord a, Num a) => a -> [a] -> a
within epsilon (x:y:ys) | canGiveAnswer x y epsilon = buildAnswer x y epsilon
| True = within epsilon (y:ys)
I'll leave it up to you to figure out what canGiveAnswer and buildAnswer are supposed to be.
within eps (x:y:xs) = .... However, you should think about the function's behaviour if the list isn't infinite and/or doesn't contain a fitting pair.ap zip tail :: [a] -> [(a,a)]