This is more of a note-to-self than an informative post. Justin Le used the Data.Interval library a few times in his Advent of Code solutions, and intervals have come up previously. As the library is new to me, this is a note to remind me to use it in future!

I'm re-doing Advent of Code 2025 day 5 using this library. See that post for a description of the problem and my solution.

The Data.IntervalSet type does what I need: it stores a bunch of intervals, combining them as needed when they overlap. That means I can read the input file into a single IntervalSet and a list of points.

rangesP = IVS.fromList <$> rangeP `sepBy` endOfLine
rangeP = rangify <$> decimal <* "-" <*> decimal
  where rangify l u = Finite l I.<=..<= Finite u

That makes solving the puzzle nearly trivial. Part 1 is "how many points are members of the interval set?":

part1 :: Ranges -> [Ingredient] -> Int
part1 ranges ingredients = length $  filter (`IVS.member` ranges) ingredients

Part 2 is "what's the widths of all the intervals?":

part2 :: Ranges -> Int
part2 = sum . fmap ((+1) . I.width) . IVS.toList

Code

You can get the code from Codeberg.