无法读取未定义的 属性 'kids' - 或者如何打破 Elm 中信号的循环依赖?

Cannot read property 'kids' of undefined - or how to break a circular dependency of signals in Elm?

虽然 elm-make 成功了,但我在浏览器中收到以下错误:

Cannot read property 'kids' of undefined

我想这是因为我有信号的循环依赖:

model -> clicks -> model

相关代码如下:

model : Signal Model
model =
  Signal.foldp update initialModel clicks


clicks : Signal Action
clicks =
  let
    clickPosition = Mouse.position
      |> Signal.sampleOn Mouse.clicks
    tuplesSignal = Signal.map3 (,,) clickPosition Window.dimensions model      
  in
    ...

感觉model在Elm中实现的很普遍,所以我应该挑战一下clicks -> model依赖。

这里是一些上下文:

我正在使用 canvas:

构建一个滑动益智游戏

当用户单击可以移动的图块时,它应该会移动。否则,应忽略点击。

clicks 将产生以下操作:LeftRightUpDown

例如,如果用户点击图块 12、11、8、15(按此顺序),clicks 应为:Down -> Right -> Up

问题是,为了计算点击了哪个图块,我需要知道图板的尺寸(例如上图中的 4 行和 4 列)。但是,电路板尺寸存储在 model 中(想象一下允许用户更改电路板尺寸的用户界面)。

如何摆脱这种循环依赖?

在这种情况下,我认为您应该在所谓的输入中走得更底层,并接受点击位置作为输入。然后你可以在你的 Signal.foldp 中组合一个 update 函数,另外两个函数:

  1. 首先将点击和模型转换为 Maybe Direction(假设 LeftRightUpDownDown 类型的构造函数=17=])
  2. 第二个函数采用 Direction 值和模型来计算新模型。您可以使用 Maybe.mapMaybe.withDefault 来处理第一个函数结果的 Maybe 部分。

将这两个部分分开,即使您立即生产和消费 Direction,也会使您的系统更加自我记录,并显示原始输入和受限 "actual" 输入之间的概念划分。

P.S。 Elm 语言有 conceivable extensions 可以让您更轻松地在信号域中编写此输入预处理。但是这样的扩展会使语言的信号部分更加强大,以至于不清楚它是否会使 "the right way" 构建程序更难发现。