Skip to content

Instantly share code, notes, and snippets.

@rupertlssmith
Last active January 11, 2018 16:19
Show Gist options
  • Save rupertlssmith/c948f304ce0a99cd7ba9d6b6a061251a to your computer and use it in GitHub Desktop.
Save rupertlssmith/c948f304ce0a99cd7ba9d6b6a061251a to your computer and use it in GitHub Desktop.
Experimenting with state machines in Elm
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)
@rupertlssmith
Copy link
Author

StateModel.elm contains some helper functions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment