【问题标题】:Handling records with shared substructure in Elm在 Elm 中处理具有共享子结构的记录
【发布时间】:2014-08-04 23:33:58
【问题描述】:

我有一些记录类型的结构基本上是这样的:

type Body x = { x | pos: (Int,Int) }
type Bubble = Body { radius: Int }
type Box = Body { width: Int, height: Int }

现在我想获得其中任何一个的混合列表,并对 Body 部分执行一些操作,但在其他时候仍然是特殊情况处理 BoxBubble。例如,有(省略了实现):

mv: (Int,Int) -> Body a -> Body a
bubble: Bubble
box: Box

我愿意

map (mv (1,1)) [box,bubble]

但这失败了,因为 Elm 认为列表中的类型不兼容。

现在我可以将 Boxes 和 Bubbles 包装在 ADT 中,如下所示:

type BodyWrap = BoxWrap Box | BubbleWrap Bubble

但是我需要在每种情况下都进行解包和重新包装。如果我想折叠混合列表,它会变得更加混乱。 this gist 中有一个示例。

有没有更优雅的方式来处理这种情况?

【问题讨论】:

  • Elm 中不能有异构列表。这意味着列表中的所有类型必须相同。您的包装解决方案将起作用,但很混乱。另一种方法是创建一个数据类型来保存您希望共有的功能(类似于 OO)。这是一篇与此相关的文章:github.com/Dobiasd/articles/blob/master/…
  • 我想我遇到了一些在 Scala 中很容易而在 Elm 中很难的东西。但是谢谢,这是一个开始!

标签: polymorphism algebraic-data-types elm


【解决方案1】:

当使用组合而不是继承时,这个问题就会消失。

不要将整个结构包装在 ADT 中,而是让记录中的一个字段包含具有对象特定属性的 ADT:

type Body = { pos: (Int,Int), shape: Shape }
data shape = Bubble Int | Box (Int,Int)

这允许使用Body 中的共享结构,同时仅在必要时匹配shape

【讨论】:

  • 你知道当一个结通过纯粹的意志力解开时的感觉吗?确切地说,你只能在编程中得到它......
猜你喜欢
  • 2017-10-03
  • 2017-02-07
  • 2021-09-25
  • 2021-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多