4c86abcf

ical-recurrence: express recurrence over a parameterised component

**1 of 4.** Groundwork for handling `RECURRENCE-ID`. **Nothing here is red**: this is a pure refactor. Every `.occ` and `.res` golden file is byte-identical, and the only new tests are `genValidSpec`s for the new types.

Sequence, each depending on the one before it: **this** → `recurrence-id` → `this-and-future` → `todo-and-journal`. I'll open the next once this is merged.

## Why the old entry points go away rather than gaining a fix

A component with a `RECURRENCE-ID` replaces the instance it names rather than adding an occurrence beside it, so the occurrences of one component depend on the other components sharing its UID. No function that takes a single component can be correct about that.

- `recur :: Day -> event -> R (Set event)` took one component and handed back a copy with a rewritten `DTSTART` and blanked recurrence properties — a component the calendar never contained.
- `recurEvents :: Day -> RecurringEvent -> R (Set EventOccurrence)` computed one component's own expansion under a name that claimed to compute a recurrence set. That expansion is still needed, so it survives as `expandRecurring`, which says what it does.

## VTODO and VJOURNAL

RFC 5545 gives `VEVENT`, `VTODO` and `VJOURNAL` the same recurrence properties, and §3.8.4.4 says `RECURRENCE-ID` identifies an instance of a "VEVENT, VTODO, or VJOURNAL". The only thing that differs is how the end of an instance is spelled: `DTEND`, `DUE`, and none respectively. `RecurrenceEnd` is that shared spelling, so a `VTODO`'s `DUE` is not typed as a `DTEND`, and `eventRecurring` / `todoRecurring` / `journalRecurring` are where the difference lives.

## The parameter

`Recurring`, `Occurrence` and `Resolved` are parameterised over the component so that one recurrence implementation serves all three, and so that a caller which has already narrowed a `VEVENT` down to what it cares about can still recur it. The `Functor` instances are how it swaps its own type in.

`HasRecurrence` is gone: a class over three known types buys nothing that three functions do not, and `makeOccurrence` existed only to hand back that never-contained component.

`ICal.Recurrence.Class` held the class, so it is renamed to `ICal.Recurrence.Types`, which is what it now holds.

---

Previously opened as #40 and merged by mistake without review; `master` has been put back to `cffbc57` and this is the same commit, unchanged.
coverage-reportforwardCompatibilitynixpkgs-25_11pre-commitconfiguredevShelldefaultx86_64-linux