Elm - 根据信号中的值更新模型

Elm - updating the model based on values in a signal

我正在使用一个端口将对象从 javascript 传递到 elm,我想根据从 JS 收到的值更新我的模型。这是我的代码:

    type alias Model = { x: String, y: String }
    type Action = Received { x: String, y: String }
    update : Action -> Model -> Model
    update action model =
        case action of
            Received rec -> { model | x = rec.x, y = rec.y }

    port rec : Signal { x: String, y: String }
    result = Signal.map update (Received rec)

但是,我在最后一行收到类型不匹配的编译器错误,说 update 在应该接收 { x: String, y: String }[=14 时接收了类型 Signal { x: String, y: String } 的参数=]

所以看起来你想要做的是从你的端口传入记录的信号到你的模型当前状态的信号。评论中提到了 foldp,它会发挥作用,所以我一定会解决它。为了从您的端口​​获取当前模型状态的信号,您的代码可能如下所示:

initialModel : Model
initialModel =
  { x = "0"
  , y = "0"
  }

result : Signal Model
result =
  rec
    |> Signal.map Received
    |> Signal.foldp update initialModel

现在让我们一步一步来。

initialModel : Model
initialModel =
  { x = "0"
  , y = "0"
  }

通过这个分配,我们设置了一个初始状态,从该状态开始。 Elm 的信号必须始终具有初始值,无论该初始值是否与您的程序相关。如果您不关心您的初始模型是什么,您可以将记录的字段分配给您想要的任何内容。

result : Signal Model
result =
  rec
    |> Signal.map Received
    -- ...

这里我们使用Signal.map从你的端口来的{ x : String, y : String }条记录到Actions的信号,即Recieved动作。所以在这个阶段我们有一个 Signal Action.

|> Signal.foldp update initialModel

在这最后一步中,我们从上一步中提取 Signal Action,并将其折叠到具有 Signal.foldp 的先前模型中。第一个参数是一个函数,它接受某种类型 a 表示来自另一个信号的传入新值(在本例中是我们的 Signal Action),以及我们状态的最后一个可用值(即 initialModel 在一开始然后是 update 的最后一个 return 值向前)和 return 是下一个状态。这就是在 Elm 应用程序中获取任何状态的方式。

result 最终成为应用程序模型的最新化身的信号,然后您可以将其映射到 HtmlGraphics.Element 或任何您想要的信号我想再次使用 Signal.map 以生成一些用户界面来响应应用程序中的更新。