2015-11-15 77 views
1

我剛進入榆樹,我被困在一見鍾情的問題看起來很簡單,但我正在努力尋找解決問題的最佳實踐。主信號中的多個信號,信號到文本

演習:

編寫一個程序,顯示了三個文本字段,垂直排列。第一個顯示當前的鼠標位置以及True或False,具體取決於鼠標左鍵是否當前關閉。第二個文本框顯示在第一個下面,根據空格鍵是否關閉顯示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 

我主不編譯,但我不知道我需要怎麼回事做到這一點。我在正確的道路上嗎?它能縮短嗎?如何在這種情況下使用體系結構模型,查看和更新​​?

任何幫助表示讚賞。

回答

4

微創

你可以去全榆木建築,但因爲這似乎是一個學習鍛鍊,讓我給你的最小變化得到它的工作:

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 
+0

謝謝你的偉大答案,但唯一缺少的是該位置必須在mouseDown旁邊。我想實現我只需要改變combineHtml方法。 – Stanko

+0

對,我可以更新我的答案以包含該內容 – Apanatshka