也许你能帮上忙。我是一名 Elm 初学者,我正在为一个相当平凡的问题而苦苦挣扎。我对 Elm 感到非常兴奋,而且我在较小的事情上相当成功,所以现在我尝试了一些更复杂的事情,但我似乎无法理解它。
我正在尝试在 Elm 中构建一些使用类似图形的底层数据结构的东西。我用这样的流畅/工厂模式创建图表:
sample : Result String MyThing
sample =
MyThing.empty
|> addNode 1 "bobble"
|> addNode 2 "why not"
|> addEdge 1 2 "some data here too"
当此代码返回 Ok MyThing
时, 那么整个图已经以一致的方式建立起来, 有保证, 即所有节点和边都具有所需的数据, 并且所有节点的边都实际存在。
实际代码具有与节点和边关联的更复杂的数据,但这对问题无关紧要。在内部,节点和边存储在 Dict Int element
中.
type alias MyThing =
{ nodes : Dict Int String
, edges : Dict Int { from : Int, to : Int, label : String }
}
现在,在模块的用户中,我想访问图形的各种元素。但是每当我使用 Dict.get
访问其中一个节点或边缘时, 我得到一个 Maybe
.这相当不方便,因为凭借我的构造函数代码,我知道索引存在等。我不想用 Maybe
使上游代码困惑。和 Result
当我知道边缘中的索引存在时。举个例子:
getNodeTexts : Edge -> MyThing -> Maybe (String, String)
getNodeTexts edge thing =
case Dict.get edge.from thing.nodes of
Nothing ->
--Yeah, actually this can never happen...
Nothing
Just fromNode -> case Dict.get edge.to thing.nodes of
Nothing ->
--Again, this can never actually happen because the builder code prevents it.
Nothing
Just toNode ->
Just ( fromNode.label, toNode.label )
这只是很多样板代码,用于处理我在工厂代码中特别阻止的事情。但更糟糕的是:现在消费者需要额外的样板代码来处理 Maybe
--可能不知道 Maybe
实际上永远不会是Nothing
. API 有点欺骗消费者。这不是 Elm 试图避免的事情吗?与假设但不正确的比较:
getNodeTexts : Edge -> MyThing -> (String, String)
getNodeTexts edge thing =
( Dict.get edge.from thing.nodes |> .label
, Dict.get edge.to thing.nodes |> .label
)
另一种方法是不使用 Int
ID 而不是使用实际数据——但是更新内容变得非常乏味,因为连接器可能有很多边缘。通过 Int
在不解耦的情况下管理状态这似乎不是个好主意。
我觉得必须使用不透明的 ID 类型来解决这个难题,但我只是没有看到。如果有任何指点,我将不胜感激。
注意:我也尝试同时使用 drathier
和 elm-community
榆 TreeMap 形库,但它们没有解决具体问题。他们依靠Dict
在下面,所以我最终得到了相同的 Maybe
最佳答案
您的问题没有简单的答案。我可以提供一条评论和编码建议。
您使用了神奇的词“不可能的状态”,但正如 OOBalance 所指出的,您可以在您的建模中创建一个不可能的状态。 Elm 中“不可能状态”的正常含义恰恰与建模有关,例如当您使用两个 Bool
来表示 3 种可能的状态时。在 Elm 中,您可以为此使用自定义类型,而不是在代码中留下一个 bool 组合。
至于你的代码,你可以减少它的长度(和复杂性)
getNodeTexts : Edge -> MyThing -> Maybe ( String, String )
getNodeTexts edge thing =
Maybe.map2 (\ n1 n2 -> ( n1.label, n2.label ))
(Dict.get edge.from thing.nodes)
(Dict.get edge.to thing.nodes)
关于graph - 在 Elm 中管理不可能状态的好模式是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59620114/