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:
-- >>> intervals 0.5 [0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0]
-- [(3,4),(8,10)]
-- >>> intervals 0.5 [1,0,0,0,1,1,0,0,0,1,1,1,0]
-- [(0,0),(4,5),(9,11)]
-- >>> 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 => a -> [a] -> [(Int, Int)]
intervals threshold ys = f False 0 p
where p = zip [0..] . map (> threshold) $ ys
f :: Bool -> Int -> [(Int, Bool)] -> [(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 && b = f True startPos ((bPos,b):as)
| a && (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