无法到达榆树 Tick 动作
Cannot reach elm Tick action
我希望有人可以在信号和效果方面帮助我。
我正在研究 Signals/Effects 并且一直在研究榆树架构,尤其是 example 8。
在此示例中(据我了解),如果您单击形状:
- 信号消息连同操作一起发送到地址
- 更新时触发
SPIN
操作
- 如果形状当前没有动画,也会调用 Tick。
我正在尝试复制完全相同的流程(使用类似的代码),但我不想点击按钮并使用 HTML 包,我只想使用空格键发送信号。
在我的代码中,空格键向 Punch
操作发送一个信号。就像示例 8 一样,我还想调用 Tick
并更新模型中的 debounceState
。
您会在我的评论中看到我可以达到我的 Punch
操作,但我似乎永远无法达到 Tick
。
我看过 ,但因为我使用的是键盘信号而不是 elm StartApp,所以我认为它不适用。
如果有人能解释为什么我无法在示例中达到 Tick
,我将不胜感激。
module Main (..) where
import Graphics.Element exposing (..)
import Time exposing (Time, second)
import Effects exposing (Effects)
import Keyboard
type alias DebounceState =
Maybe
{ prevClockTime : Time
, elapsedTime : Time
}
type alias Model =
{ punching : Bool
, count : Int
, randomString: String
, debounceState : DebounceState
}
duration = second
-- MODEL
initialModel : ( Model, Effects Action )
initialModel =
( { punching = False
, count = 0
, randomString = ""
, debounceState = Nothing
}
, Effects.none
)
model : Signal ( Model, Effects Action )
model =
Signal.foldp update initialModel (punch Keyboard.space)
-- ACTIONS
type Action
= NoOp
| Punch Bool
| Tick Time
-- UPDATE
update : Action -> ( Model, Effects Action ) -> ( Model, Effects Action )
update action ( model, fx ) =
case action of
NoOp ->
( model, Effects.none )
Punch isPunching ->
case model.debounceState of
Nothing ->
( { model |
punching = isPunching
, count = model.count + 1 }, Effects.tick Tick )
Just _ ->
( { model |
punching = isPunching
, count = model.count + 2 }, Effects.none )
-- I don't seem to reach `Tick` at all
-- You'll notice that I try to apply a value to `randomString` in the
-- conditional to indicate where I end up
Tick clockTime ->
let
newElapsedTime =
case model.debounceState of
Nothing ->
0
Just {elapsedTime, prevClockTime} ->
elapsedTime + (clockTime - prevClockTime)
in
if newElapsedTime > duration then
( {model | randomString = "foo"} , Effects.none )
else
( {model | randomString = "bar"} , Effects.tick Tick )
-- SIGNAL
punch : Signal Bool -> Signal Action
punch input =
Signal.map Punch input
-- VIEW
view : ( Model, Effects Action ) -> Element
view model =
show model
main : Signal Element
main =
Signal.map view model
直接粘贴到 Try Elm。
Tick
操作从未触发,因为没有端口将 Effects
传输到 Tasks
。在您发布的相关 Stack Overflow 答案中,正在使用 StartApp
,因此连接端口很容易。
由于您没有使用 StartApp
,因此您需要手动执行一些操作。现在,您的 model
只听到键盘 space 信号。您需要连接信号处理,以便您的效果一直返回到触发您的 update
功能。
您需要一个邮箱来协调信号。
actions : Signal.Mailbox (List Action)
actions =
Signal.mailbox []
请注意,此邮箱是根据操作列表定义的。这是将 Effects 转换为 Tasks 的复杂部分之一,它是 explained here.
现在您需要一个端口来获取 (Model, Effects Action)
元组的第二部分并将其转换为 Task
.
port effects : Signal (Task.Task Effects.Never ())
port effects =
Signal.map (Effects.toTask actions.address << snd) model
该端口现在会将您的 Tick
操作发送到邮箱,但我们仍未连接您的模型以同时收听键盘 space 键和这个新邮箱。为此,我们将使用 Signal.mergeMany
.
signals : Signal Action
signals =
let
singleAction list =
case list of
[] -> NoOp
(a::_) -> a
in
Signal.mergeMany
[ punch Keyboard.space
, Signal.map singleAction actions.signal
]
singleAction
函数中发生的有趣事情只是让我们了解了这样一个事实,即 Effects.toTask
迫使我们使用 Actions
的列表而不是单个 Action
.查看文档,很明显我们可以安全地从列表中删除第一个元素。
现在我们有了一个由键盘 space 栏和 Tick 动作触发的信号。最后一部分是让 model
收听该信号而不仅仅是键盘。
model : Signal ( Model, Effects Action )
model =
Signal.foldp update initialModel signals
我希望有人可以在信号和效果方面帮助我。
我正在研究 Signals/Effects 并且一直在研究榆树架构,尤其是 example 8。
在此示例中(据我了解),如果您单击形状:
- 信号消息连同操作一起发送到地址
- 更新时触发
SPIN
操作 - 如果形状当前没有动画,也会调用 Tick。
我正在尝试复制完全相同的流程(使用类似的代码),但我不想点击按钮并使用 HTML 包,我只想使用空格键发送信号。
在我的代码中,空格键向 Punch
操作发送一个信号。就像示例 8 一样,我还想调用 Tick
并更新模型中的 debounceState
。
您会在我的评论中看到我可以达到我的 Punch
操作,但我似乎永远无法达到 Tick
。
我看过
如果有人能解释为什么我无法在示例中达到 Tick
,我将不胜感激。
module Main (..) where
import Graphics.Element exposing (..)
import Time exposing (Time, second)
import Effects exposing (Effects)
import Keyboard
type alias DebounceState =
Maybe
{ prevClockTime : Time
, elapsedTime : Time
}
type alias Model =
{ punching : Bool
, count : Int
, randomString: String
, debounceState : DebounceState
}
duration = second
-- MODEL
initialModel : ( Model, Effects Action )
initialModel =
( { punching = False
, count = 0
, randomString = ""
, debounceState = Nothing
}
, Effects.none
)
model : Signal ( Model, Effects Action )
model =
Signal.foldp update initialModel (punch Keyboard.space)
-- ACTIONS
type Action
= NoOp
| Punch Bool
| Tick Time
-- UPDATE
update : Action -> ( Model, Effects Action ) -> ( Model, Effects Action )
update action ( model, fx ) =
case action of
NoOp ->
( model, Effects.none )
Punch isPunching ->
case model.debounceState of
Nothing ->
( { model |
punching = isPunching
, count = model.count + 1 }, Effects.tick Tick )
Just _ ->
( { model |
punching = isPunching
, count = model.count + 2 }, Effects.none )
-- I don't seem to reach `Tick` at all
-- You'll notice that I try to apply a value to `randomString` in the
-- conditional to indicate where I end up
Tick clockTime ->
let
newElapsedTime =
case model.debounceState of
Nothing ->
0
Just {elapsedTime, prevClockTime} ->
elapsedTime + (clockTime - prevClockTime)
in
if newElapsedTime > duration then
( {model | randomString = "foo"} , Effects.none )
else
( {model | randomString = "bar"} , Effects.tick Tick )
-- SIGNAL
punch : Signal Bool -> Signal Action
punch input =
Signal.map Punch input
-- VIEW
view : ( Model, Effects Action ) -> Element
view model =
show model
main : Signal Element
main =
Signal.map view model
直接粘贴到 Try Elm。
Tick
操作从未触发,因为没有端口将 Effects
传输到 Tasks
。在您发布的相关 Stack Overflow 答案中,正在使用 StartApp
,因此连接端口很容易。
由于您没有使用 StartApp
,因此您需要手动执行一些操作。现在,您的 model
只听到键盘 space 信号。您需要连接信号处理,以便您的效果一直返回到触发您的 update
功能。
您需要一个邮箱来协调信号。
actions : Signal.Mailbox (List Action)
actions =
Signal.mailbox []
请注意,此邮箱是根据操作列表定义的。这是将 Effects 转换为 Tasks 的复杂部分之一,它是 explained here.
现在您需要一个端口来获取 (Model, Effects Action)
元组的第二部分并将其转换为 Task
.
port effects : Signal (Task.Task Effects.Never ())
port effects =
Signal.map (Effects.toTask actions.address << snd) model
该端口现在会将您的 Tick
操作发送到邮箱,但我们仍未连接您的模型以同时收听键盘 space 键和这个新邮箱。为此,我们将使用 Signal.mergeMany
.
signals : Signal Action
signals =
let
singleAction list =
case list of
[] -> NoOp
(a::_) -> a
in
Signal.mergeMany
[ punch Keyboard.space
, Signal.map singleAction actions.signal
]
singleAction
函数中发生的有趣事情只是让我们了解了这样一个事实,即 Effects.toTask
迫使我们使用 Actions
的列表而不是单个 Action
.查看文档,很明显我们可以安全地从列表中删除第一个元素。
现在我们有了一个由键盘 space 栏和 Tick 动作触发的信号。最后一部分是让 model
收听该信号而不仅仅是键盘。
model : Signal ( Model, Effects Action )
model =
Signal.foldp update initialModel signals