A function determining intervals of values greater than threshold I wonder if there exists a shorter/more elegant functional programming way than listing all the possible cases. Here, a function that determines positions of beginning/end of subintervals greater than threshold is coded. The idea behind the listed code is to mark and retain the beginning of such an interval, then to push a tuple of (beginning,ending) as soon as the interval ends. Feel free to choose any other approach if needed.

-- | Determines the intervals greater than threshold.
--
-- Examples:
-- &gt;&gt;&gt; intervals 0.5 [0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0]
-- [(3,4),(8,10)]
-- &gt;&gt;&gt; intervals 0.5 [1,0,0,0,1,1,0,0,0,1,1,1,0]
-- [(0,0),(4,5),(9,11)]
-- &gt;&gt;&gt; intervals 0.5 [1,0,0,0,1,1,0,0,0,1,1,1,0,1,1,1]
-- [(0,0),(4,5),(9,11),(13,15)]
intervals :: Ord a =&gt; a -&gt; [a] -&gt; [(Int, Int)]
intervals threshold ys = f False 0 p
  where p = zip [0..] . map (&gt; threshold) $ ys
        f :: Bool -&gt; Int -&gt; [(Int, Bool)] -&gt; [(Int, Int)]
        f _ _ [] = []
        f True startPos ((bPos,b):[]) | b = [(startPos, bPos)]
                                      | otherwise = [(startPos, startPos)]
        f False _ ((bPos,b):[]) | b = [(bPos, bPos)]
                                | otherwise = []
        f True startPos ((aPos,a):(bPos,b):as) | a &amp;&amp; b = f True startPos ((bPos,b):as)
                                               | a &amp;&amp; (not b) = ((startPos, aPos)) : (f False 0 as)
                                               | otherwise = (startPos, startPos) : (f False 0 ((bPos,b):as))
        f False _ ((aPos,a):as) | a = f True aPos as
                                | otherwise = f False 0 as
(You can skip right to TL;DR for a simpler approach)

Your function actually determines the indices of list elements that are above a threshold. In Haskell, when you have a list, an index is not the idiomatic way to represent its items. What do you want with those indices?

Agreed, your version is hard to read. For another approach, I start with

intervalsT :: [Bool] -&gt; [(Int, Int]


and notice that the group function might come in handy to collect subsequent equal elements.

*Main&gt; group [True,True,False,False,True]
[[True,True],[False,False],[True]]


mapping length will result in [2,2,1], which is a step closer to the indices. To turn [a,b,c] into [0,a ,a+b, a+b+c], the function scanl' is perfect:

*Main&gt; scanl' (+) 0 [2,2,1]
[0,2,4,5]


which we can zip with its own tail. But wait! We lost information whether something is above or below threshold.
zip it again with the grouped Bools, filter based on the bools, throw away the bools. This yields:

TL;DR

intervals p = intervalsT . map (&gt;p)
intervalsT :: [Bool] -&gt; [(Int,Int)]
intervalsT xs = let grouped = group xs
                    idx = scanl' (+) 0 . map length $ grouped
                    ivs = zip idx (map (subtract 1) $ tail idx)
                 in map snd $ filter fst $ zip (map head grouped) ivs