Run Updates sequentially.
import Update exposing (Update)
import Update.Sequence as Sequence exposing (Sequence)
type Value
= Start
| ClickNext
| SubmitText
| NeverUsed
type Msg
= SequenceMsg (Sequence.Msg Value)
type alias Model =
{ sequence : Sequence.Model
, notice : String
, text : String
}
update : Msg -> Update Model Msg
update (SequenceMsg msg) =
Sequence.run
{ get = .sequence
, set = \seq model -> { model | sequence = seq }
}
msg
[ Sequence.on Start
[ setNotice "Tutorial has started!"
]
, Sequence.on ClickNext
[ setNotice "The first next button is clicked."
]
, Sequence.on ClickNext
[ setNotice "The second next button is clicked."
]
, \v -> Sequence.when (v == SubmitText) <| Sequence.with <| \{ text } ->
if text == "" then
Sequence.waitAgain <|
setNotice "Invalid text. Retry!"
else
Sequence.succeed <|
setNotice <| text ++ " is submitted."
, Sequence.on ClickNext
[ setNotice "The last next button is clicked."
]
]
-- Helper functions
setNotice : String -> Update Model msg
setNotice notice = Update.modify <| \model -> { model | notice = notice }
-- Test the update function
model0 : Model
model0 =
{ sequence = Sequence.initModel
, notice = "initial"
, text = "initial text"
}
model1 : Model
model1 =
Update.run
(update <| SequenceMsg <| Sequence.resolve Start)
model0
|> Tuple.first
model1.notice
--> "Tutorial has started!"
model2 : Model
model2 =
Update.run
(update <| SequenceMsg <| Sequence.resolve ClickNext)
model1
|> Tuple.first
model2.notice
--> "The first next button is clicked."
-- Notice that here we provide the very same event as previous.
model3 : Model
model3 =
Update.run
(update <| SequenceMsg <| Sequence.resolve ClickNext)
model2
|> Tuple.first
model3.notice
--> "The second next button is clicked."
-- The result shows that we get the second notice rather than the first one.
model4 : Model
model4 =
Update.run
(update <| SequenceMsg <| Sequence.resolve SubmitText)
{ model3 | text = "" }
|> Tuple.first
model4.notice
--> "Invalid text. Retry!"
-- Notice that here we provides the resulting `model4`, but not the previous `model3` again.
model5 : Model
model5 =
Update.run
(update <| SequenceMsg <| Sequence.resolve SubmitText)
{ model4 | text = "valid text" }
|> Tuple.first
model5.notice
--> "valid text is submitted."
-- The result shows that we can retry the current `Sequence`.
model6 : Model
model6 =
Update.run
(update <| SequenceMsg <| Sequence.resolve <| ClickNext)
model5
|> Tuple.first
model6.notice
--> "The last next button is clicked."Construct a Sequence always succeeds with given Updates.
Construct a Sequence always wait again after evaluating given Updates.
Succeed Sequence only if it meets the condition.
Otherwise, it waitAgain with Update.none.
Succeed Sequence unless it meets the condition.
Otherwise, it waitAgain with Update.none.
Generate a Sequence that succeeds only under certain value.
It succeeds with Updates only if the fired message value is equals to its first argument, otherwise it waitAgain with Update.none.
Generate a Sequence that succeeds only under certain values.
It succeeds with Updates only if the fired message value is one of its first argument, otherwise it waitAgain with Update.none.
Evaluate Sequences from top to bottom.
Once a Sequence succeeds, it does not evaluate subsequent Sequences.
Sequence.anyOf
[ Sequence.on ClickOk
[ setNotice "Ok"
]
, Sequence.on ClickNg
[ setNotice "Ng"
]
]Generate a Sequence that succeeds only on Just values.
It succeeds with Updates only if the value is Just, otherwise it waitAgain with Update.none.
Generate a Sequence that succeeds only on Nothing values.
It succeeds with Updates only if the value is Nothing, otherwise it waitAgain with Update.none.
Generate a Sequence that succeeds only on Ok values.
It succeeds with Updates only if the value is Ok, otherwise it waitAgain with Update.none.