This is an example of coding a state machine in Elm.
For a better example, see this one: [ https://gist.github.com/rupertlssmith/88946c8d207d7ad64daf4360fef1ac42 ]
This is an example of coding a state machine in Elm.
For a better example, see this one: [ https://gist.github.com/rupertlssmith/88946c8d207d7ad64daf4360fef1ac42 ]
type alias WithContent = | |
{ contentItem : Content } | |
type alias WithSelectedModel = | |
{ contentModel : ContentModel | |
, overlay : Overlay.Model | |
} | |
type alias WithInlineEditor = | |
{ inlineEditorStyle : Animation.State | |
} | |
type Mode | |
= Loading | |
| Explore WithContent | |
| Markdown WithContent WithSelectedModel | |
| Preview WithContent WithSelectedModel | |
| Wysiwyg WithContent WithSelectedModel WithInlineEditor | |
type alias Model = | |
{ mode : Mode | |
, menu : Menu | |
} | |
maybeLoading : Mode -> Maybe Mode | |
maybeLoading state = | |
case state of | |
Loading -> | |
Just state | |
_ -> | |
Nothing | |
-- ... more maybeState functions | |
mapWhenWithContent : (WithContent -> a) -> Mode -> Maybe a | |
mapWhenWithContent func state = | |
case state of | |
Explore content -> | |
Just <| func content | |
Markdown content _ -> | |
Just <| func content | |
Preview content _ -> | |
Just <| func content | |
Wysiwyg content _ _ -> | |
Just <| func content | |
_ -> | |
Nothing | |
-- ... More mapWhen functions | |
updateWhenWithContent : (WithContent -> WithContent) -> Mode -> Maybe Mode | |
updateWhenWithContent func state = | |
case state of | |
Explore content -> | |
func content |> Explore |> Just | |
Markdown content selected -> | |
func content |> (flip Markdown) selected |> Just | |
Preview content selected -> | |
func content |> (flip Preview) selected |> Just | |
Wysiwyg content selected inline -> | |
func content |> (swirll Wysiwyg) selected inline |> Just | |
_ -> | |
Nothing | |
-- ... More updateWhen functions | |
-- State transition functions - these may contain custom logic, unlike the above which area really just boilerplate. | |
toLoading : Mode -> Mode | |
toLoading _ = | |
Loading | |
toExplore : WithContent -> Mode -> Maybe Mode | |
toExplore content state = | |
case state of | |
Loading -> | |
Nothing | |
_ -> | |
Explore content |> Just | |
toMarkdown : WithSelectedModel -> Mode -> Maybe Mode | |
toMarkdown selected state = | |
case state of | |
Loading -> | |
Nothing | |
_ -> | |
mapWhenWithContent | |
(\content -> | |
Markdown content selected | |
) | |
state | |
toPreview : WithSelectedModel -> Mode -> Maybe Mode | |
toPreview selected state = | |
case state of | |
Loading -> | |
Nothing | |
_ -> | |
mapWhenWithContent | |
(\content -> | |
Preview content selected | |
) | |
state | |
toWysiwyg : WithSelectedModel -> WithInlineEditor -> Mode -> Maybe Mode | |
toWysiwyg selected inline state = | |
case state of | |
Loading -> | |
Nothing | |
_ -> | |
mapWhenWithContent | |
(\content -> | |
Wysiwyg content selected inline | |
) | |
state | |
module StateModel | |
exposing | |
( boolToMaybe | |
, (>&&>) | |
, (>||>) | |
, defaultTransition | |
, mapWhenCompose | |
) | |
import Maybe exposing (andThen) | |
import Maybe.Extra exposing (orElse) | |
boolToMaybe : (a -> Bool) -> a -> Maybe a | |
boolToMaybe filter val = | |
if filter val then | |
Just val | |
else | |
Nothing | |
(>&&>) : (a -> Maybe b) -> (b -> Maybe c) -> a -> Maybe c | |
(>&&>) fst snd val = | |
fst val |> andThen snd | |
(>||>) : (a -> Maybe b) -> (a -> Maybe b) -> a -> Maybe b | |
(>||>) fst snd val = | |
fst val |> orElse (snd val) | |
defaultTransition state trans = | |
trans state |> Maybe.withDefault state | |
mapWhenCompose : (c -> d -> Maybe a) -> (a -> d -> Maybe b) -> c -> d -> Maybe b | |
mapWhenCompose mapWhen1 mapWhen2 func state = | |
mapWhen1 func state | |
|> andThen ((flip mapWhen2) state) |
StateModel.elm contains some helper functions.