主信号中的多个信号,信号到文本

Multiple signals in main, signals to text

我刚接触 Elm,我遇到了一个问题,乍一看很简单,但我正在努力寻找解决问题的最佳实践。

练习:

编写一个程序,显示三个垂直排列的文本字段。第一个显示当前鼠标位置和 True 或 False,具体取决于鼠标左键当前是否按下。第二个文本框显示在第一个文本框下方,并根据 space 栏是否向下显示 True 或 False。最后,第三个文本字段显示 Keyboard.arrows 的当前值。试用生成的程序,以便了解所有这些输入信号的行为。

我的代码:

import Keyboard
import Mouse
import Html exposing ( Html )

main = 
  Signal.map mapStringToHtml position,
  Signal.map mapStringToHtml mouseDown,
  Signal.map mapStringToHtml spaceDown,
  Signal.map mapStringToHtml arrows

mapStringToHtml : String -> Html
mapStringToHtml x = Html.text x

position : Signal String
position = Signal.map toString Mouse.position

mouseDown : Signal String
mouseDown = Signal.map toString Mouse.isDown

spaceDown : Signal String
spaceDown = Signal.map toString Keyboard.space

arrows : Signal String
arrows = Signal.map toString Keyboard.arrows

我的 main 没有编译,但我不知道我还需要怎么做。我在正确的道路上吗?能再短点吗?在这种情况下如何使用架构模型、视图、更新?

感谢任何帮助。

微创

你可以使用完整的 Elm 架构,但由于这似乎是一个学习练习,让我给你最小的改变来让它工作:

main =
  Signal.map4 combineHtml
    (Signal.map mapStringToHtml position)
    (Signal.map mapStringToHtml mouseDown)
    (Signal.map mapStringToHtml spaceDown)
    (Signal.map mapStringToHtml arrows)

combineHtml pos mouse space arr =
  Html.div [] [pos, mouse, space, arr]

mapStringToHtml : String -> Html
mapStringToHtml x = Html.div [] [Html.text x]

所以每段文字都有自己的div。 combineHtml 通过将它们放在另一个 div 中来组合所有这些。我认为这是快速将它们全部放在单独一行上的最简单方法。

要将 div 的 个信号 合并为一个,我们使用 Signal.map4。它需要一个带有四个参数和四个信号的函数。每次其中一个信号更新时,都会使用信号的最新值评估函数。

重写

最小的更改对所有信息都一视同仁,并将它们全部放在单独的一行中。但问题包括鼠标位置和按钮应该在同一行上。所以这里是重写的程序,代码重复也少了一点:

import Keyboard
import Mouse
import Html exposing ( Html )

main = Signal.map4 view
  Mouse.position
  Mouse.isDown
  Keyboard.space
  Keyboard.arrows

view position mouseDown spaceDown arrows =
  let
    div  = Html.div []
    text = toString >> Html.text
    spacer = Html.text " "
  in
    div
      [ div [ text position, spacer, text mouseDown ]
      , div [ text spaceDown ]
      , div [ text arrows ]
      ]

let-in 构造定义了一些局部常量。 divHtml.div 的快捷方式,其中第一个参数始终为空列表。 text 是一个函数,它首先应用 toString,然后应用 Html.text 的结果。这些函数的长格式是:

    div children = Html.div [] children
    text something = Html.text (toString something)
    -- or as pipeline: text something = something |> toString |> Html.text