在Haskell中设计数据类型时,我经常遇到的一个问题是使用sum类型或Maybe Eithers的记录.
一个简单的例子是对FX操作,现货或远期操作进行建模,其中唯一的区别在于是否存在"到期日"(一种方式是使用和类型,如果它是一个点或前方则明确指定.
data Amount = Amount { amount :: Double, currency :: String }
data Fx = Spot { tranDate :: Day, soldAmount :: Amount, boughtAmount :: Amount }
| Forward { tranDate :: Day, paidAmount :: Amount, boughtAmount :: Amount , maturity :: Day}
Run Code Online (Sandbox Code Playgroud)
另一种方法就是把它maturity作为"可能"
data Fx = Fx { tranDate :: Day
, soldAmount :: Amount
, boughtAmount :: Amount
, maturity (Maybe Day)
}
Run Code Online (Sandbox Code Playgroud)
或其他任何东西
我不建议使用具有命名字段的sum类型.它们对仅存在于其中一个分支上的访问器不安全.如果你有重复的字段,它们就不会很干.
但是我不是把Maybe记录放在里面,而是定义一个包装记录,如下所示:
data Spot = Spot
{ tranDate :: Day
, soldAmount :: Amount
, boughtAmount :: Amount
}
data Forward = Forward
{ spot :: Spot
, maturity :: Day
}
Run Code Online (Sandbox Code Playgroud)
也许甚至是HasSpot类型类为好,既Spot和Forward将实施.
但现在很难将Spot和Forward值放在同一个集合中.也许可以使用类似(Maybe Day, Spot)的情况.
然而,这个答案的"包装"方法并不能很好地概括为多个可选字段.