As always recursions consists out of two parts:
one or more base cases, here for instance the empty list:
inRange _ _ [] = []
on or more recursive cases (or inductive cases). Evidently, this is the case when the list is not empty.
Now for the latter, there are two options: either the first number of the list is in the range, or it is not. In case it is, we enumerate it, in case it is not, we do not enumerate:
inRange a b (x:xs) | a <= x && x <= b = x : tl
| otherwise = tl
where tl = inRange a b xs
So the full implementation reads:
inRange a b (x:xs) | a <= x && x <= b = x : tl
| otherwise = tl
where tl = inRange a b xs
inRange _ _ _ = []
Here we have written the base case at the bottom: the advantage is that - at least conceptually - Haskell evaluates from top to bottom, and evidently it is less likely the list will be empty.
Furthermore we can use don't cares (_) on all parameters such that we are certain all possible cases are covered and thus that the function is at least total (meaning for any kind of input, you will always receive output, although this evidently does not prove correctness).