There's no need to be flippant.
My goal is exactly what I said. Right now I've got 29 identical structs that differ only in which protocols they conform to (from GitHub - davedelong/time: Building a better date/time library for Swift)
(Identical initializers omitted for brevity)
public struct Era: EraField {
public let region: Region
public let dateComponents: DateComponents
}
public struct Year: EraField, YearField {
public let region: Region
public let dateComponents: DateComponents
}
public struct YearMonth: EraField, YearField, MonthField {
public let region: Region
public let dateComponents: DateComponents
}
public struct YearMonthDay: EraField, YearField, MonthField, DayField {
public let region: Region
public let dateComponents: DateComponents
}
public struct YearMonthDayHour: EraField, YearField, MonthField, DayField, HourField {
public let region: Region
public let dateComponents: DateComponents
}
public struct YearMonthDayHourMinute: EraField, YearField, MonthField, DayField, HourField, MinuteField {
public let region: Region
public let dateComponents: DateComponents
}
public struct YearMonthDayHourMinuteSecond: EraField, YearField, MonthField, DayField, HourField, MinuteField, SecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct YearMonthDayHourMinuteSecondNanosecond: EraField, YearField, MonthField, DayField, HourField, MinuteField, SecondField, NanosecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct Month: MonthField {
public let region: Region
public let dateComponents: DateComponents
}
public struct MonthDay: MonthField, DayField {
public let region: Region
public let dateComponents: DateComponents
}
public struct MonthDayHour: MonthField, DayField, HourField {
public let region: Region
public let dateComponents: DateComponents
}
public struct MonthDayHourMinute: MonthField, DayField, HourField, MinuteField {
public let region: Region
public let dateComponents: DateComponents
}
public struct MonthDayHourMinuteSecond: MonthField, DayField, HourField, MinuteField, SecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct MonthDayHourMinuteSecondNanosecond: MonthField, DayField, HourField, MinuteField, SecondField, NanosecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct Day: DayField {
public let region: Region
public let dateComponents: DateComponents
}
public struct DayHour: DayField, HourField {
public let region: Region
public let dateComponents: DateComponents
}
public struct DayHourMinute: DayField, HourField, MinuteField {
public let region: Region
public let dateComponents: DateComponents
}
public struct DayHourMinuteSecond: DayField, HourField, MinuteField, SecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct DayHourMinuteSecondNanosecond: DayField, HourField, MinuteField, SecondField, NanosecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct Hour: HourField {
public let region: Region
public let dateComponents: DateComponents
}
public struct HourMinute: HourField, MinuteField {
public let region: Region
public let dateComponents: DateComponents
}
public struct HourMinuteSecond: HourField, MinuteField, SecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct HourMinuteSecondNanosecond: HourField, MinuteField, SecondField, NanosecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct Minute: MinuteField {
public let region: Region
public let dateComponents: DateComponents
}
public struct MinuteSecond: MinuteField, SecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct MinuteSecondNanosecond: MinuteField, SecondField, NanosecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct Second: SecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct SecondNanosecond: SecondField, NanosecondField {
public let region: Region
public let dateComponents: DateComponents
}
public struct Nanosecond: NanosecondField {
public let region: Region
public let dateComponents: DateComponents
}
In my library, these types are organized in 13 different files, which makes them difficult to discover. It also over-emphasizes their relative importance compared to the rest of the library. These are, fundamentally, simple model objects. However, the fact that they're scattered across so many files makes the overall domain seem more complicated than it already is. It increases maintenance time and mental load.
I would love to find a way to have a single CalendarValue<...>
type, where the generic parameters indicate the particular values/constraints/concepts represented by the value. This would mean I could focus on the parts of my library that are actually useful, instead of the bookkeeping necessary to make sure I'm keeping all 29 structs in sync.