Haskell记录字段依赖性

时间:2018-03-29 16:16:12

标签: haskell

Shape

numberOfSides可以是三角形,四边形等,具体取决于data MyRecord = MyRecord { players :: [Player], numOfPlayers :: Int }

我的问题是:这两个领域是相关的。当一个字段更新时,是否有“触发”机制来更新另一个?如果这两个字段存在冲突,那么报告类型错误?

另一个相关场景:

numberOfPlayers

我想以某种方式根据players的大小自动计算{{1}}。

PS:这是否与 GADT 依赖类型有某种关联?

2 个答案:

答案 0 :(得分:2)

在Haskell中,与OO语言不同,您无法修改字段。因此,通常的方法,即我认为你正在考虑的,有一个明确的“setter”在Haskell中没有意义。最简单的事情,这与DRY principle(在函数式语言以及OO语言中非常相关)完全一致,只是存储其中一个字段而另一个是访问者,如上所述在评论中。

-- deriving (...) clauses and other boilerplate omitted for brevity

data Shape = Triangle | Quad | Pentagon | Other

data MyRecord = MyRecord Int

numSides :: Shape -> Int
numSides Triangle = 3
numSides Quad = 4
numSides Pentagon = 5
numSides Other = 0

shape :: Int -> Shape
shape 3 = Triangle
shape 4 = Quad
shape 5 = Pentagon
shape _ = Other

makeMyRecord :: Shape -> MyRecord
makeMyRecord = MyRecord . numSides

numberOfSides :: MyRecord -> Int
numberOfSides (MyRecord x) = x

shapeOf :: MyRecord -> Shape
shapeOf = shape . numberOfSides

现在,Shape可以是EnumBounded,如果您还没有这样做的话。从那里开始,shapenumSides可以根据自动生成的Enum实例缩短。如果您希望能够从MyRecord构建Int,则可以导出数据构造函数或定义另一个makeMyRecord'来执行此操作。现在,由于我们正在使用DRY原则,您可以让用户自由更新字段,另一个“字段”将会神奇地更新。

答案 1 :(得分:1)

  

我的问题是:这两个领域是相关的。是否有"触发器"更新一个字段时更新另一个的机制?如果这两个字段存在冲突,那么报告类型错误?

     

PS:这是否与GADT和依赖类型有关?

这与依赖类型有关,但与GADT无关。由于这是Haskell,我建议只需在记录中存储边数,然后编写函数numTypes :: Int -> Shape