为了在 Haskell 中实现可视化的算术表达式编辑器,我定义了以下内容:
data AST = Lit Int
| Add AST AST
| Neg AST
eval :: AST -> Int
type TagName = String
type Attrs = M.Map String String
data DOM = Tag TagName Attrs [SubDOM]
data SubDOM = SubNode DOM | Text String
toDOM :: AST -> DOM
fromDOM :: DOM -> AST
我想让用户可以同时编辑 AST 和 DOM,并在它们之间同步用户操作(例如将子节点替换为另一个),此外,我希望有效地同步操作(这意味着只有修改后的子节点应该重建),我应该如何处理这个?
一种解决方案是为每个 AST 节点和 DOM 节点分配一个 id,当一侧发生操作时,我们将此操作同步到具有相同 id 的另一侧节点,但这一步在函数式编程中似乎很棘手,我问了这个问题单独:如何在函数式编程中为 AST 节点生成稳定的 id?.
另一种解决方案是重新定义数据结构,让一侧保留另一侧的IORef,当操作发生时,我们可以通过引用将操作同步到另一侧。但这种方法似乎不起作用。
那么,在函数式编程中是否有解决这个问题的最佳实践?