我在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}
另一种方法是将maturity
作为“可能”
data Fx = Fx { tranDate :: Day
, soldAmount :: Amount
, boughtAmount :: Amount
, maturity (Maybe Day)
}
或其他任何东西
答案 0 :(得分:5)
我不建议使用具有命名字段的和类型。它们对仅存在于其中一个分支上的访问器不安全。如果你有重复的字段,它们就不会很干。
但是我不是将Maybe
放在记录中,而是定义一个包装记录,如下所示:
data Spot = Spot
{ tranDate :: Day
, soldAmount :: Amount
, boughtAmount :: Amount
}
data Forward = Forward
{ spot :: Spot
, maturity :: Day
}
甚至可能是HasSpot
类型类,Spot
和Forward
都会实现。
但现在很难将Spot和Forward值放在同一个集合中。在这种情况下,也许可以使用类似(Maybe Day, Spot)
的类型。
"包装"但是,这个答案的方法并不能很好地概括为多个可选字段。
答案 1 :(得分:1)
第二个例子没有很好的沟通。你必须检查maturity
以区分前锋和现场。总和类型传达得更好。