Рассмотрим тип DateTime, в котором должна присутствовать дата, но временная часть в секундах является необязательной. Если часть времени есть, может быть и дополнительная часть в миллисекундах. Если миллисекунды присутствуют, может быть и наносекундная часть.
Есть много способов справиться с этим, например:
--rely on smart constructors
data DateTime = DateTime { days:: Int,
sec :: Maybe Int,
ms :: Maybe Int,
ns :: Maybe Int
}
-- list all possibilities
data DateTime = DateOnly Int
| DateWithSec Int Int
| DateWithMilliSec Int Int Int
| DateWithNanoSec Int Int Int Int
-- cascaded Maybe
data DateTime = DateTime Int (Maybe (Int, Maybe (Int, Maybe Int)))
-- cascaded data
data Nano = NoNano | Nano Int
data MilliSec = NoMilliSec | MilliSec Int Nano
data Sec = NoSec | Sec Int MilliSec
data Date = Date Int Sec
Какую конструкцию вы бы использовали (конечно, не ограничиваясь приведенными выше примерами) и почему?
[намерения]
Я изучаю возможности типа даты в Frege (http://code.google.com/p/frege/), используя date4j DateTime
в качестве ориентирной линии ( поскольку Haskell дата и время lib слишком сложны, а java.util.Date
слишком сломан). В моей текущей реализации игрушек все поля обязательны, но, конечно, было бы неплохо освободить пользователя от нежелательной точности (а исходная реализация имеет необязательные поля).
Итак, основные цели:
- безопасность: нелегальные государства следует избегать любой ценой.
- удобство: должно быть легко работать с типом, например. сопоставление шаблонов было бы круто, календарные вычисления должны быть легкими...
Не так важно:
- производительность: Конечно, работа с типом не должна быть слишком медленной, но для типичного использования ей не нужно зацикливать последний такт
- memory: в случаях, когда это действительно имеет значение, было бы легко получить более компактный формат хранения
- краткая реализация: это библиотека, и я готов добавить весь код, необходимый для того, чтобы сделать вещи гладкими.
Тем не менее, все это очень условно и не следует воспринимать слишком серьезно.