考虑一个 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/),使用 date4jDateTime
作为指导方针(因为 Haskell 的日期和时间库太复杂了,java.util.Date
太破碎了)。在我当前的玩具实现中,所有字段都是必需的,但当然最好将用户从不需要的精度中解放出来(并且原始实现具有可选字段)。
所以主要目标是:
- 安全:必须不惜一切代价避免非法状态
- 方便:使用类型应该很容易,例如模式匹配会很酷,日历计算应该很容易......
不那么重要的是:
- 性能:当然,使用类型不应该太慢,但对于典型的用法,它不必挤出最后一个时钟周期
- 内存:在这很重要的情况下,很容易推导出更紧凑的存储格式
- 简洁的实现:这是一个库,我愿意添加使事情顺利进行所需的所有代码
也就是说,所有这些都是非常试探性的,不应该太认真。