edkelly303 / elm-any-type-forms / Control

Creating a form


type alias Control state delta output =
AdvancedControl output state delta output

A Control is the basic unit from which forms are composed. This library provides various example controls and combinators that you can use to build a form for any arbitrarily complex Elm type.


type alias Form state delta output msg =
{ blank : ( State state
, Platform.Cmd.Cmd msg )
, prefill : output -> ( State state
, Platform.Cmd.Cmd msg )
, update : Delta delta -> State state -> ( State state
, Platform.Cmd.Cmd msg )
, view : State state -> Html msg
, subscriptions : State state -> Platform.Sub.Sub msg
, submit : State state -> ( State state
, Result (List Feedback) output ) 
}

A Form is an interface containing functions that you can use in your Elm Program to initialise, view, update, subscribe, and submit your form.

sandbox : { outputToString : output -> String, control : Control state delta output } -> Platform.Program () (State state) (Delta delta)

Test and debug a Control by turning it into a Program that you can run as a standalone Elm application.

This is useful when you're rapidly iterating on designing a form, and you don't yet want the hassle of plumbing it into your main Elm application's Modeland Msg types.

Once you're happy with the form, you can then ask the Elm repl (or your editor's Elm plugin) to tell you the type signature of the Program, which will give you the form's State and Delta types. You can then plug these into your main Modeland Msg types wherever appropriate.

main : Program () (State String) (Delta String)
main =
    sandbox
        { control = int
        , outputToString = Debug.toString
        }

simpleForm : { control : Control state delta output, onUpdate : Delta delta -> msg, onSubmit : msg } -> Form state delta output msg

Convert a Control into a simple Form, rendered as a list of controls wrapped in an HTML <form> element, with a submit button at the bottom.

You will need to supply a couple of variants from your app's Msg type: one to handle updates of the form's state, and one to handle the submission of the form, as follows:

type alias Msg
    = FormUpdated (Delta String)
    | FormSubmitted

mySimpleForm : Form (State String) (Delta String) Int Msg
mySimpleForm =
    form
        { control = int
        , onUpdate = FormUpdated
        , onSubmit = FormSubmitted
        }

Now you can integrate your Form into a larger Elm app:

  1. Call mySimpleForm.blank or mySimpleForm.prefill in your init function.
  2. Call mySimpleForm.update in the FormUpdated branch of your update function.
  3. Call mySimpleForm.submit in the FormSubmitted branch of your update function.
  4. Call mySimpleForm.view in your view function.
  5. Call mySimpleForm.subscriptions in your subscriptions function.

form : { control : Control state delta output, onUpdate : Delta delta -> msg, view : List (Html msg) -> Html msg } -> Form state delta output msg

Convert a Control into a Form, and render the form however you like.

You will need to supply a variant from your app's Msg type to handle updates of the form's state. You will also need to supply a view function that takes the List (Html msg) produced by the supplied Control and returns an Html msg, as follows:

type alias Msg
    = FormUpdated (Delta String)
    | FormSubmitted

myForm : Form (State String) (Delta String) Int Msg
myForm =
    form
        { control = int
        , onUpdate = FormUpdated
        , view =
            \controlView ->
                H.form
                    [ HE.onSubmit FormSubmitted ]
                    (controlView ++ [ H.button [ HA.type_ "submit" ] [ H.text "Submit" ] ])
        }

Now you can integrate your Form into a larger Elm app:

  1. Call myForm.blank or myForm.prefill in your init function.
  2. Call myForm.update in the FormUpdated branch of your update function.
  3. Call myForm.submit in the FormSubmitted branch of your update function.
  4. Call myForm.view in your view function.
  5. Call myForm.subscriptions in your subscriptions function.

Basic controls

bool : Control Basics.Bool Basics.Bool Basics.Bool

A control that produces a Bool. Renders as an HTML checkbox.

int : Control String String Basics.Int

A control that produces an Int. Renders as an HTML number input.

float : Control String String Basics.Float

A control that produces a Float. Renders as an HTML number input.

string : Control String String String

A control that produces a String. Renders as an HTML text input.

char : Control String String Char

A control that produces a Char. Renders as an HTML text input.

enum : ( String, enum ) -> ( String, enum ) -> List ( String, enum ) -> Control enum enum enum

A control that produces a custom type where none of the variants have any payload. Renders as an HTML radio input.

type Colour
    = Red
    | Green
    | Blue

colourControl : Control Colour Colour Colour
colourControl =
    enum
        ( "Red", Red )
        ( "Green", Green )
        [ ( "Blue", Blue ) ]

Basic combinators

tuple : Control state1 delta1 output1 -> Control state2 delta2 output2 -> Control ( State state1, ( State state2, End ) ) ( Delta delta1, ( Delta delta2, End ) ) ( output1, output2 )

A combinator that produces a tuple of two controls of given types.

myTupleControl =
    tuple string int

triple : Control state1 delta1 output1 -> Control state2 delta2 output2 -> Control state3 delta3 output3 -> Control ( State state1, ( State state2, ( State state3, End ) ) ) ( Delta delta1, ( Delta delta2, ( Delta delta3, End ) ) ) ( output1, output2, output3 )

A combinator that produces a triple of three controls of given types.

myTripleControl =
    triple string int float

maybe : Control state delta output -> Control ( State (), ( State ( State state, End ), End ) ) ( Delta (), ( Delta ( Delta delta, End ), End ) ) (Maybe output)

A combinator that produces a Maybe of a control of a given type.

myMaybeControl =
    maybe int

result : Control failureState failureDelta failureOutput -> Control successState successDelta successOutput -> Control ( State ( State failureState, End ), ( State ( State successState, End ), End ) ) ( Delta ( Delta failureDelta, End ), ( Delta ( Delta successDelta, End ), End ) ) (Result failureOutput successOutput)

A combinator that produces a Result with a given error and success type.

myResultControl =
    result string int

list : Control state delta output -> Control (List (State state)) (ListDelta delta) (List output)

A combinator that produces a List of controls of a given type.

myListControl =
    list int

dict : Control keyState keyDelta comparable -> Control valueState valueDelta value -> Control ( State (List (State ( State keyState, ( State valueState, End ) ))), End ) ( Delta (ListDelta ( Delta keyDelta, ( Delta valueDelta, End ) )), End ) (Dict comparable value)

A combinator that produces a Dict from controls of given key and value types. The key type must be comparable.

myDictControl =
    dict int string

set : Control state delta comparable -> Control ( State (List (State state)), End ) ( Delta (ListDelta delta), End ) (Set comparable)

A combinator that produces a Set from controls of a given member types. The member type must be comparable.

mySetControl =
    set string

array : Control state delta output -> Control ( State (List (State state)), End ) ( Delta (ListDelta delta), End ) (Array output)

A combinator that produces an Array from a control of a given type.

myArrayControl =
    array int

map : { convert : a -> b, revert : b -> a } -> Control state delta a -> Control ( State state, End ) ( Delta delta, End ) b

A combinator that converts a Control whose output is of type a to a Control whose output is of type b.

This is particularly useful for implementing "wrapper" types, such as Ids.

Note: with most common map functions, such as List.map, we only need to supply a function from a -> b. In this case, however, we need to supply two functions that will allow us to both convert the type from a -> b and revert it back from b -> a.

type Id
    = Id Int

idControl =
    map
        { convert = \i -> Id i
        , revert = \(Id i) -> i
        }
        int

Creating a new control


type alias ControlConfig state delta output =
{ blank : ( state
, Platform.Cmd.Cmd delta )
, prefill : output -> ( state
, Platform.Cmd.Cmd delta )
, update : delta -> state -> ( state
, Platform.Cmd.Cmd delta )
, view : { label : String
, id : String
, name : String
, class : String
, state : state } -> List (Html delta)
, subscriptions : state -> Platform.Sub.Sub delta
, parse : state -> Result (List String) output
, label : String 
}

Configuration for a custom control. You need to supply the following fields:

create : ControlConfig state delta output -> Control state delta output

Create a simple control, with any arbitrary state and delta types, and producing any arbitrary output type.

Here's how we could create a control like the famous counter example from the Elm Guide

type CounterDelta
    = Increment
    | Decrement

counterControl : Control Int CounterDelta Int
counterControl =
    create
        { blank = 0
        , prefill = identity
        , update =
            \delta state ->
                case delta of
                    Increment ->
                        state + 1

                    Decrement ->
                        state - 1
        , view =
            \{ state, name, id, label, class } ->
                Html.div [ Html.Attributes.class class ]
                    [ Html.label
                        [ Html.Attributes.for id ]
                        [ Html.text label ]
                    , Html.div
                        [ Html.Attributes.id id
                        , Html.Attributes.name name
                        ]
                        [ Html.button
                            [ Html.Attributes.type_ "button"
                            , Html.Events.onClick Increment
                            ]
                            [ Html.text "+" ]
                        , Html.div [] [ Html.text <| String.fromInt state ]
                        , Html.button
                            [ Html.Attributes.type_ "button"
                            , Html.Events.onClick Decrement
                            ]
                            [ Html.text "-" ]
                        ]
                    ]
        , subscriptions = \state -> Sub.none
        , parse = Ok
        }

Validating controls

Simple validation

failIf : (output -> Basics.Bool) -> String -> Control state delta output -> Control state delta output

Display an error on a Control if its output fails to meet the predicate.

This causes the Control to fail validation.

positiveInt =
    int
        |> failIf
            (\x -> x < 1)
            "This must be greater than zero!"

noteIf : (output -> Basics.Bool) -> String -> Control state delta output -> Control state delta output

Display an note on a Control if its output fails to meet the predicate.

This just shows the user a message - it doesn't cause the Control to fail validation.

positiveInt =
    int
        |> noteIf
            (\x -> x < 1)
            "Should this be greater than zero?"

Multi-field validation

You may want display errors on one or more controls based on the validation of another control higher up the tree.

Take the example of a password creation form. You want to validate that the "Enter password" and "Confirm password" fields both contain the same string, and show a helpful error message on the "Confirm password" field if they don't. You can achieve this as follows:

passwordControl =
    record
        (\password confirmation ->
            { password = password
            , confirmation = confirmation
            }
        )
        |> field string
        |> field
            (string
                |> respond
                    { alert = "passwords-do-not-match"
                    , fail = True
                    , message = "Must match 'Enter password' field"
                    }
            )
        |> endRecord
        |> alertIf
            (\{ password, confirmation } ->
                password /= confirmation
            )
            "passwords-do-not-match"

alertIf : (output -> Basics.Bool) -> String -> Control state delta output -> Control state delta output

Emit an alert from a Control if its output fails to meet the predicate.

This is meant to be used in combination with respond, which listens for the alert and displays an error or notification message on the appropriate control(s).

respond : { alert : String, fail : Basics.Bool, message : String } -> Control state delta output -> Control state delta output

Respond to an alert emitted by another Control, display an error or notification message on this control, and if desired, cause validation to fail.

This is meant to be used in combination with alertIf, which emits the alert.

List validation

alertAtIndexes : (output -> List Basics.Int) -> String -> Control (List state) (ListDelta delta) output -> Control (List state) (ListDelta delta) output

Conditionally display an error on one or more items in a list control, based on the output of the list control.

The following example will display errors on the first two items in a list of strings, if and only if those first two items are "hello" and "world":

myString =
    string
        |> catch
            { alert = "no-hello-world"
            , fail = True
            , message = "The first two items in the list must not be \"hello\" and \"world\"."
            }

myList =
    list myString
        |> alertAtIndexes
            (\list_ ->
                case list of
                    "hello" :: "world" :: _ ->
                        [ 0, 1 ]

                    _ ->
                        []
            )
            "no-hello-world"

Configuring controls

default : input -> AdvancedControl input state delta output -> AdvancedControl input state delta output

Set a default output value for a Control.

oneAndHello =
    tuple int string
        |> default ( 1, "hello" )

debounce : Basics.Float -> Control state delta output -> Control state delta output

Debounce a Control for a number of milliseconds before it will display any parsing or validation errors. This can be used to allow the user to finish typing into a text input before we show them feedback.

sluggishStringControl =
    string
        |> debounce 2000

id : String -> Control state delta output -> Control state delta output

Set an id for a Control.

myStringControlHasAnId =
    string
        |> id "my-string"

name : String -> Control state delta output -> Control state delta output

Set a name for a Control.

myStringControlHasAName =
    string
        |> name "My string"

label : String -> AdvancedControl input state delta output -> AdvancedControl input state delta output

Set a label for a Control.

myStringControlHasALabel =
    string
        |> label "Enter your name"

class : String -> Control state delta output -> Control state delta output

Add an HTML class attribute for a Control. See docs for Html.Attributes.class in elm-html.

myStringControlHasAClass =
    string
        |> class "important"
        |> class "no-really"

classList : List ( String, Basics.Bool ) -> Control state delta output -> Control state delta output

Add a list of HTML class attributes to a Control. See docs for Html.Attributes.classList in the elm/html package.

myStringControlHasClasses =
    string
        |> classList
            [ ( "important", True )
            , ( "no-really", True )
            , ( "ignore-me", False )
            ]

wrapView : (List (Html (Delta delta)) -> List (Html (Delta delta))) -> Control state delta output -> Control state delta output

Transform the HTML output of a Control's view function.

wrappedInt =
    int
        |> wrapView (\view -> [ Html.div [] view ])

Building record combinators


type RecordBuilder after afters before befores debouncingReceiverCollector deltaInitialiser errorCollector alertEmitter fns idleSetter initialDeltas initialStates initialiser makeSetters parser subscriptionCollector toOutput updater viewer

A data structure used to build records

record : toOutput -> RecordBuilder End End (a12 -> a12) (a11 -> a11) (a10 -> a10) (a9 -> a9) (a8 -> a8) (a7 -> a7) (b -> c -> c) (a6 -> a6) (d -> e -> e) (f -> g -> g) (a5 -> a5) (a4 -> a4) (a3 -> a3) (a2 -> a2) toOutput (a1 -> a1) (a -> a)

A combinator that produces a record type, or any 'product' type that needs to be constructed from multiple controls. (For example, the tuple combinator in this library is built using the record combinator).

type alias MyRecord =
    { name : String
    , age : Int
    }

myRecordControl =
    record
        (\name age ->
            { name = name
            , age = age
            }
        )
        |> field string
        |> field int
        |> endRecord

field : (recordOutput8 -> output7) -> AdvancedControl input8 state9 delta12 output7 -> RecordBuilder after1 afters1 (( Delta delta13, a18 ) -> c5) (( ( Delta delta13, a18 ) -> c5, a17 ) -> c4) (a16 -> List Alert -> restFns7 -> restStates7 -> List Alert) (a15 -> List (Platform.Cmd.Cmd delta1_1) -> restDeltaSetters2 -> restDeltas2 -> List (Platform.Cmd.Cmd delta1_1)) (a14 -> List Alert -> List Feedback -> restFns6 -> restStates6 -> List Feedback) (a13 -> List Alert -> restFns5 -> restStates5 -> List Alert) (Path -> ( RecordFns input8 state9 delta12 output7 recordOutput8, a12 ) -> c3) (a11 -> restFns4 -> restStates4 -> restStates4) (Path -> ( Platform.Cmd.Cmd (Delta delta12), a10 ) -> c2) (Path -> ( State state9, a9 ) -> c1) (a8 -> (a7 -> c) -> List (Platform.Cmd.Cmd msg1) -> a5 -> b -> d -> e) (a4 -> befores -> afters -> next) (a3 -> Result (List Feedback) output1_1 -> restFns3 -> restStates3 -> Result (List Feedback) output2_1) (a2 -> List (Platform.Sub.Sub msg) -> restDeltas1 -> restFns2 -> restStates2 -> List (Platform.Sub.Sub msg)) toOutput (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta1), newStates : restStates1 -> recordState0 } -> restFns1 -> restDeltaSetters1 -> restDeltas -> restStates1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta1), newStates : recordState }) (a -> List (Subcontrol recordDelta) -> List Alert -> restFns -> restDeltaSetters -> restStates -> List (Subcontrol recordDelta)) -> RecordBuilder ( Delta delta11, after1 ) ( after1, afters1 ) (a18 -> c5) (a17 -> c4) (a16 -> List Alert -> ( RecordFns input7 state8 delta10 output6 recordOutput7, restFns7 ) -> ( State state8, restStates7 ) -> List Alert) (a15 -> List (Platform.Cmd.Cmd delta1_1) -> ( delta9 -> delta1_1, restDeltaSetters2 ) -> ( Platform.Cmd.Cmd delta9, restDeltas2 ) -> List (Platform.Cmd.Cmd delta1_1)) (a14 -> List Alert -> List Feedback -> ( RecordFns input6 state7 delta8 output5 recordOutput6, restFns6 ) -> ( State state7, restStates6 ) -> List Feedback) (a13 -> List Alert -> ( RecordFns input5 state6 delta7 output4 recordOutput5, restFns5 ) -> ( State state6, restStates5 ) -> List Alert) (Path -> a12 -> c3) (a11 -> ( RecordFns input4 state5 delta6 output3 recordOutput4, restFns4 ) -> ( State state5, restStates4 ) -> ( State state5, restStates4 )) (Path -> a10 -> c2) (Path -> a9 -> c1) (a8 -> (( State state4, a7 ) -> c) -> List (Platform.Cmd.Cmd msg1) -> a5 -> ( RecordFns a6 state4 delta5 a6 a5, b ) -> ( Delta delta5 -> msg1, d ) -> e) (a4 -> ( ( value, after ) -> delta4, befores ) -> ( after, afters ) -> ( value -> delta4, next )) (a3 -> Result (List Feedback) (output0 -> output1_1) -> ( RecordFns input3 state3 delta3 output0 recordOutput3, restFns3 ) -> ( State state3, restStates3 ) -> Result (List Feedback) output2_1) (a2 -> List (Platform.Sub.Sub msg) -> ( Delta delta2 -> msg, restDeltas1 ) -> ( RecordFns input2 state2 delta2 output2 recordOutput2, restFns2 ) -> ( State state2, restStates2 ) -> List (Platform.Sub.Sub msg)) toOutput (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta1), newStates : ( State state1, restStates1 ) -> recordState0 } -> ( RecordFns input1 state1 delta1 output1 recordOutput1, restFns1 ) -> ( Delta delta1 -> recordDelta1, restDeltaSetters1 ) -> ( Delta delta1, restDeltas ) -> ( State state1, restStates1 ) -> { newCmds : List (Platform.Cmd.Cmd recordDelta1), newStates : recordState }) (a -> List (Subcontrol recordDelta) -> List Alert -> ( RecordFns input state delta output recordOutput, restFns ) -> ( Delta delta -> recordDelta, restDeltaSetters ) -> ( State state, restStates ) -> List (Subcontrol recordDelta))

Add a field to a record combinator.

type alias Hello =
    { hello : String }

helloControl =
    record Hello
        |> field string
        |> endRecord

endRecord : RecordBuilder after afters before (End -> befores) ((List Alert -> End -> End -> List Alert) -> List Alert -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( State state, restStates ) -> List Alert) ((List (Platform.Cmd.Cmd ( Delta delta, restDeltas )) -> End -> End -> List (Platform.Cmd.Cmd ( Delta delta, restDeltas ))) -> List (Platform.Cmd.Cmd ( Delta delta, restDeltas )) -> ( Delta delta -> recordDelta, restSetters ) -> deltas -> List (Platform.Cmd.Cmd ( Delta delta, restDeltas ))) ((List Alert -> List Feedback -> End -> End -> List Feedback) -> List Alert -> List Feedback -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( State state, restStates ) -> List Feedback) ((List Alert -> End -> End -> List Alert) -> List Alert -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( State state, restStates ) -> List Alert) (Path -> End -> ( RecordFns input1 state delta output1 recordInput, restFns )) ((End -> End -> End) -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( State state, restStates ) -> ( State state, restStates )) (Path -> End -> deltas) (Path -> End -> ( State state, restStates )) (((End -> state1) -> List (Platform.Cmd.Cmd msg) -> b -> End -> End -> ( State state1, Platform.Cmd.Cmd (Delta msg) )) -> (a -> a) -> List c -> input -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( Delta delta -> recordDelta, restSetters ) -> ( State ( State state, restStates ), Platform.Cmd.Cmd (Delta ( Delta delta, restDeltas )) )) ((End -> End -> End) -> befores -> afters -> ( Delta delta -> recordDelta, restSetters )) ((Result (List Feedback) output -> End -> End -> Result (List Feedback) output) -> Result (List Feedback) output1_1 -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( State state, restStates ) -> Result (List Feedback) output) ((List (Platform.Sub.Sub ( Delta delta, restDeltas )) -> End -> End -> End -> List (Platform.Sub.Sub ( Delta delta, restDeltas ))) -> List (Platform.Sub.Sub ( Delta delta, restDeltas )) -> ( Delta delta -> recordDelta, restSetters ) -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( State state, restStates ) -> List (Platform.Sub.Sub ( Delta delta, restDeltas ))) output1_1 (({ newCmds : List (Platform.Cmd.Cmd ( Delta delta, restDeltas )), newStates : End -> ( State state, restStates ) } -> End -> End -> End -> End -> { newCmds : List (Platform.Cmd.Cmd ( Delta delta, restDeltas )), newStates : End -> ( State state, restStates ) }) -> { newCmds : List (Platform.Cmd.Cmd ( Delta delta, restDeltas )), newStates : ( State state, restStates ) -> ( State state, restStates ) } -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( Delta delta -> recordDelta, restSetters ) -> ( Delta delta, restDeltas ) -> ( State state, restStates ) -> { newCmds : List (Platform.Cmd.Cmd ( Delta delta, restDeltas )), newStates : End -> ( State state, restStates ) }) ((List (Subcontrol ( Delta delta, restDeltas )) -> List Alert -> End -> End -> End -> List (Subcontrol ( Delta delta, restDeltas ))) -> List (Subcontrol ( Delta delta, restDeltas )) -> List Alert -> ( RecordFns input1 state delta output1 recordInput, restFns ) -> ( Delta delta -> recordDelta, restSetters ) -> ( State state, restStates ) -> List (Subcontrol ( Delta delta, restDeltas ))) -> AdvancedControl input ( State state, restStates ) ( Delta delta, restDeltas ) output

Finalise the construction of a record combinator.

type alias Hello =
    { hello : String }

helloControl =
    record Hello
        |> field string
        |> endRecord


type alias LayoutConfig delta =
{ selected : Basics.Int
, selectMsg : Basics.Int -> Delta delta
, id : String
, label : String
, class : String 
}

Configuration for the layout function


type alias Subcontrol delta =
{ html : List (Html (Delta delta))
, label : String
, index : Basics.Int 
}

Data used by the layout function to render a subcontrol of a combinator.

layout : (LayoutConfig delta -> List (Subcontrol delta) -> List (Html (Delta delta))) -> Control state delta output -> Control state delta output

Define the HTML output for a combinator.

This is useful if you want to alter the way that the combinator's subcontrols are laid out on the screen.

For example, you could use it to present a record control as a wizard, rather than a list. The wizard example below is very naive, but hopefully gives you the idea.

type alias MyRecord =
    { name : String
    , age : Int
    }

myRecordControl =
    record
        (\name age ->
            { name = name
            , age = age
            }
        )
        |> field string
        |> field int
        |> endRecord
        |> layout wizard

wizard config subcontrols =
    let
        currentPage =
            config.selected

        totalPages =
            List.length subcontrols

        currentPageView =
            subcontrols
                |> List.filter (\{ index } -> index == currentPage)
                |> List.map .html
                |> List.concat

        nextClicked =
            config.selectMsg (currentPage + 1)

        backClicked =
            config.selectMsg (currentPage - 1)

        navigationButton txt msg =
            Html.button
                [ Html.Attributes.type_ "button"
                , Html.Events.onClick msg
                ]
                [ Html.text txt ]
    in
    Html.div
        [ Html.Attributes.id config.id
        , Html.Attributes.class config.class
        ]
        ([ Html.h1 [] [ Html.text "Wizard!" ]
         , navigationButton "Back" backClicked
         , Html.text
            (String.join " "
                [ "page"
                , String.fromInt currentPage
                , "of"
                , String.fromInt totalPages
                ]
            )
         , navigationButton "Next" nextClicked
         ]
            ++ currentPageView
        )

Building custom type combinators


type CustomTypeBuilder applyInputs debouncingReceiverCollector deltaAfter deltaAfters deltaBefore deltaBefores destructor errorCollector alertEmitter fns idleSetter initialDeltas initialStates initialiseDeltas makeDeltaSetters makeStateSetters parser stateAfter stateAfters stateBefore stateBefores stateInserter subscriptionCollector toArgStates updater viewer

A data structure used to build custom types

customType : destructor -> CustomTypeBuilder (applyInputs -> applyInputs) (debouncingReceiverCollector -> debouncingReceiverCollector) End End (deltaBefore -> deltaBefore) (deltaBefores -> deltaBefores) destructor (errorCollector -> errorCollector) (alertEmitter -> alertEmitter) (Path -> fns -> fns) (idleSetter -> idleSetter) (Path -> initialDeltas -> initialDeltas) (Path -> initialStates -> initialStates) (initialiseDeltas -> initialiseDeltas) (makeDeltaSetters -> makeDeltaSetters) (makeStateSetters -> makeStateSetters) (parser -> parser) End End (stateBefore -> stateBefore) (stateBefores -> stateBefores) (stateInserter -> stateInserter) (subscriptionCollector -> subscriptionCollector) (toArgStates -> toArgStates) (updater -> updater) (viewer -> viewer)

A combinator that produces a custom type.

type MyCustomType
    = NoArgs
    | OneArg String
    | TwoArgs Int Float

myCustomTypeControl =
    customType
        (\noArgs oneArg twoArgs tag ->
            case tag of
                NoArgs ->
                    noArgs

                OneArg arg1 ->
                    oneArg arg1

                TwoArgs arg1 arg2 ->
                    TwoArgs arg1 arg2
        )
        |> tag0 "NoArgs" NoArgs
        |> tag1 "OneArg" OneArg string
        |> tag2 "TwoArgs" TwoArgs int float
        |> endCustomType

tag0 : String -> output9 -> CustomTypeBuilder (a21 -> destructor1 -> restInputToStateConverters -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> restFns7 -> restStates8 -> List Alert) deltaAfter deltaAfters (( Delta delta14, a19 ) -> c7) (( ( Delta delta14, a19 ) -> c7, a18 ) -> c6) destructor (a17 -> List Alert -> List Feedback -> restFns6 -> restStates7 -> List Feedback) (a16 -> List Alert -> Basics.Int -> restFns5 -> restStates6 -> List Alert) (Path -> ( ControlFns output9 () () output9, a15 ) -> c5) (a14 -> Basics.Int -> restFns4 -> restStates5 -> restStates5) (Path -> ( Platform.Cmd.Cmd (Delta ()), a13 ) -> c4) (Path -> ( State (), a12 ) -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> restDeltaSetters2 -> restDeltas1 -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> befores -> afters -> next) (a9 -> { controlFns : restControlFns, deltaSetters : restDeltaSetters1, finalTagStates : nextFinalTagState -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : restInputTuplizers, maybeOverridesAfter : restMaybeOverridesAfter, maybeOverridesBefore : restMaybeOverridesBefore, tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> restFns3 -> restStates3 -> Result (List Feedback) output3) stateAfter stateAfters (( Maybe a23, a6 ) -> c2) (( ( Maybe a23, a6 ) -> c2, a5 ) -> c1) (a4 -> Basics.Int -> Basics.Int -> (restArgStates -> tagStates) -> restMaybeArgStates -> restArgStates -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> restSetters1 -> restFns2 -> restStates2 -> List (Platform.Sub.Sub delta1_1)) (( (output9 -> b) -> b, a2 ) -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : restStates1 -> recordState0 } -> restFns1 -> restDeltaSetters -> restDeltas -> restStates1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> restFns -> restSetters -> restStates -> List (Subcontrol delta)) -> CustomTypeBuilder (a21 -> (inputToStateConverter -> destructor1) -> ( inputToStateConverter, restInputToStateConverters ) -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> ( ControlFns input8 state8 delta11 output8, restFns7 ) -> ( State state8, restStates8 ) -> List Alert) ( Delta delta10, deltaAfter ) ( deltaAfter, deltaAfters ) (a19 -> c7) (a18 -> c6) destructor (a17 -> List Alert -> List Feedback -> ( ControlFns input7 state7 delta9 output7, restFns6 ) -> ( State state7, restStates7 ) -> List Feedback) (a16 -> List Alert -> Basics.Int -> ( ControlFns input6 state6 delta8 output6, restFns5 ) -> ( State state6, restStates6 ) -> List Alert) (Path -> a15 -> c5) (a14 -> Basics.Int -> ( ControlFns input5 state5 delta7 output5, restFns4 ) -> ( State state5, restStates5 ) -> ( State state5, restStates5 )) (Path -> a13 -> c4) (Path -> a12 -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> ( delta6 -> delta1_2, restDeltaSetters2 ) -> ( Platform.Cmd.Cmd delta6, restDeltas1 ) -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> ( ( value, after ) -> delta5, befores ) -> ( after, afters ) -> ( value -> delta5, next )) (a9 -> { controlFns : ( ControlFns input4 state1_1 delta4 output4, restControlFns ), deltaSetters : ( Delta delta4 -> tagDelta, restDeltaSetters1 ), finalTagStates : ( finalTagState, nextFinalTagState ) -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : ( (input4 -> ( State tagStates1, Platform.Cmd.Cmd (Delta tagDelta) )) -> finalTagState, restInputTuplizers ), maybeOverridesAfter : ( maybeOverrideAfter, restMaybeOverridesAfter ), maybeOverridesBefore : ( ( Maybe (State state1_1), maybeOverrideAfter ) -> ( Maybe (State state4), restMaybeStates ), restMaybeOverridesBefore ), tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> ( ControlFns input3 state3 delta3 output3, restFns3 ) -> ( State state3, restStates3 ) -> Result (List Feedback) output3) ( Maybe a7, stateAfter ) ( stateAfter, stateAfters ) (a6 -> c2) (a5 -> c1) (a4 -> Basics.Int -> Basics.Int -> (( State argState, restArgStates ) -> tagStates) -> ( Maybe (State argState), restMaybeArgStates ) -> ( State argState, restArgStates ) -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> ( Delta delta2 -> delta1_1, restSetters1 ) -> ( ControlFns input2 state2 delta2 output2, restFns2 ) -> ( State state2, restStates2 ) -> List (Platform.Sub.Sub delta1_1)) (a2 -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : ( State state1, restStates1 ) -> recordState0 } -> ( ControlFns input1 state1 delta1 output1, restFns1 ) -> ( Delta delta1 -> recordDelta, restDeltaSetters ) -> ( Delta delta1, restDeltas ) -> ( State state1, restStates1 ) -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> ( ControlFns input state e output, restFns ) -> ( Delta e -> delta, restSetters ) -> ( State state, restStates ) -> List (Subcontrol delta))

Add a tag with no arguments to a custom type.

type Unit
    = Unit

unitControl =
    customType
        (\unit tag ->
            case tag of
                Unit ->
                    unit
        )
        |> tag0 "Unit" Unit
        |> endCustomType

tag1 : String -> (output10 -> output9) -> AdvancedControl output10 state9 delta13 output10 -> CustomTypeBuilder (a21 -> destructor1 -> restInputToStateConverters -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> restFns7 -> restStates8 -> List Alert) deltaAfter deltaAfters (( Delta delta14, a19 ) -> c7) (( ( Delta delta14, a19 ) -> c7, a18 ) -> c6) destructor (a17 -> List Alert -> List Feedback -> restFns6 -> restStates7 -> List Feedback) (a16 -> List Alert -> Basics.Int -> restFns5 -> restStates6 -> List Alert) (Path -> ( ControlFns ( output10, b ) ( State state9, End ) ( Delta delta13, End ) output9, a15 ) -> c5) (a14 -> Basics.Int -> restFns4 -> restStates5 -> restStates5) (Path -> ( Platform.Cmd.Cmd (Delta ( Delta delta13, End )), a13 ) -> c4) (Path -> ( State ( State state9, End ), a12 ) -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> restDeltaSetters2 -> restDeltas1 -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> befores -> afters -> next) (a9 -> { controlFns : restControlFns, deltaSetters : restDeltaSetters1, finalTagStates : nextFinalTagState -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : restInputTuplizers, maybeOverridesAfter : restMaybeOverridesAfter, maybeOverridesBefore : restMaybeOverridesBefore, tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> restFns3 -> restStates3 -> Result (List Feedback) output3) stateAfter stateAfters (( Maybe a23, a6 ) -> c2) (( ( Maybe a23, a6 ) -> c2, a5 ) -> c1) (a4 -> Basics.Int -> Basics.Int -> (restArgStates -> tagStates) -> restMaybeArgStates -> restArgStates -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> restSetters1 -> restFns2 -> restStates2 -> List (Platform.Sub.Sub delta1_1)) (( (( d, End ) -> f) -> d -> f, a2 ) -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : restStates1 -> recordState0 } -> restFns1 -> restDeltaSetters -> restDeltas -> restStates1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> restFns -> restSetters -> restStates -> List (Subcontrol delta)) -> CustomTypeBuilder (a21 -> (inputToStateConverter -> destructor1) -> ( inputToStateConverter, restInputToStateConverters ) -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> ( ControlFns input8 state8 delta11 output8, restFns7 ) -> ( State state8, restStates8 ) -> List Alert) ( Delta delta10, deltaAfter ) ( deltaAfter, deltaAfters ) (a19 -> c7) (a18 -> c6) destructor (a17 -> List Alert -> List Feedback -> ( ControlFns input7 state7 delta9 output7, restFns6 ) -> ( State state7, restStates7 ) -> List Feedback) (a16 -> List Alert -> Basics.Int -> ( ControlFns input6 state6 delta8 output6, restFns5 ) -> ( State state6, restStates6 ) -> List Alert) (Path -> a15 -> c5) (a14 -> Basics.Int -> ( ControlFns input5 state5 delta7 output5, restFns4 ) -> ( State state5, restStates5 ) -> ( State state5, restStates5 )) (Path -> a13 -> c4) (Path -> a12 -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> ( delta6 -> delta1_2, restDeltaSetters2 ) -> ( Platform.Cmd.Cmd delta6, restDeltas1 ) -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> ( ( value, after ) -> delta5, befores ) -> ( after, afters ) -> ( value -> delta5, next )) (a9 -> { controlFns : ( ControlFns input4 state1_1 delta4 output4, restControlFns ), deltaSetters : ( Delta delta4 -> tagDelta, restDeltaSetters1 ), finalTagStates : ( finalTagState, nextFinalTagState ) -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : ( (input4 -> ( State tagStates1, Platform.Cmd.Cmd (Delta tagDelta) )) -> finalTagState, restInputTuplizers ), maybeOverridesAfter : ( maybeOverrideAfter, restMaybeOverridesAfter ), maybeOverridesBefore : ( ( Maybe (State state1_1), maybeOverrideAfter ) -> ( Maybe (State state4), restMaybeStates ), restMaybeOverridesBefore ), tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> ( ControlFns input3 state3 delta3 output3, restFns3 ) -> ( State state3, restStates3 ) -> Result (List Feedback) output3) ( Maybe a7, stateAfter ) ( stateAfter, stateAfters ) (a6 -> c2) (a5 -> c1) (a4 -> Basics.Int -> Basics.Int -> (( State argState, restArgStates ) -> tagStates) -> ( Maybe (State argState), restMaybeArgStates ) -> ( State argState, restArgStates ) -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> ( Delta delta2 -> delta1_1, restSetters1 ) -> ( ControlFns input2 state2 delta2 output2, restFns2 ) -> ( State state2, restStates2 ) -> List (Platform.Sub.Sub delta1_1)) (a2 -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : ( State state1, restStates1 ) -> recordState0 } -> ( ControlFns input1 state1 delta1 output1, restFns1 ) -> ( Delta delta1 -> recordDelta, restDeltaSetters ) -> ( Delta delta1, restDeltas ) -> ( State state1, restStates1 ) -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> ( ControlFns input state e output, restFns ) -> ( Delta e -> delta, restSetters ) -> ( State state, restStates ) -> List (Subcontrol delta))

Add a tag with one argument to a custom type.

type alias MyResult =
    Result String Int

myResultControl =
    customType
        (\ok err tag ->
            case tag of
                Ok value ->
                    ok value

                Err error ->
                    err error
        )
        |> tag1 "Ok" Ok int
        |> tag1 "Err" Err string
        |> endCustomType

tag2 : String -> (output11 -> output10 -> output9) -> AdvancedControl output11 state10 delta14 output11 -> AdvancedControl output10 state9 delta13 output10 -> CustomTypeBuilder (a21 -> destructor1 -> restInputToStateConverters -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> restFns7 -> restStates8 -> List Alert) deltaAfter deltaAfters (( Delta delta14_1, a19 ) -> c7) (( ( Delta delta14_1, a19 ) -> c7, a18 ) -> c6) destructor (a17 -> List Alert -> List Feedback -> restFns6 -> restStates7 -> List Feedback) (a16 -> List Alert -> Basics.Int -> restFns5 -> restStates6 -> List Alert) (Path -> ( ControlFns ( output11, ( output10, b ) ) ( State state10, ( State state9, End ) ) ( Delta delta14, ( Delta delta13, End ) ) output9, a15 ) -> c5) (a14 -> Basics.Int -> restFns4 -> restStates5 -> restStates5) (Path -> ( Platform.Cmd.Cmd (Delta ( Delta delta14, ( Delta delta13, End ) )), a13 ) -> c4) (Path -> ( State ( State state10, ( State state9, End ) ), a12 ) -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> restDeltaSetters2 -> restDeltas1 -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> befores -> afters -> next) (a9 -> { controlFns : restControlFns, deltaSetters : restDeltaSetters1, finalTagStates : nextFinalTagState -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : restInputTuplizers, maybeOverridesAfter : restMaybeOverridesAfter, maybeOverridesBefore : restMaybeOverridesBefore, tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> restFns3 -> restStates3 -> Result (List Feedback) output3) stateAfter stateAfters (( Maybe a23, a6 ) -> c2) (( ( Maybe a23, a6 ) -> c2, a5 ) -> c1) (a4 -> Basics.Int -> Basics.Int -> (restArgStates -> tagStates) -> restMaybeArgStates -> restArgStates -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> restSetters1 -> restFns2 -> restStates2 -> List (Platform.Sub.Sub delta1_1)) (( (( d, ( f, End ) ) -> g) -> d -> f -> g, a2 ) -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : restStates1 -> recordState0 } -> restFns1 -> restDeltaSetters -> restDeltas -> restStates1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> restFns -> restSetters -> restStates -> List (Subcontrol delta)) -> CustomTypeBuilder (a21 -> (inputToStateConverter -> destructor1) -> ( inputToStateConverter, restInputToStateConverters ) -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> ( ControlFns input8 state8 delta11 output8, restFns7 ) -> ( State state8, restStates8 ) -> List Alert) ( Delta delta10, deltaAfter ) ( deltaAfter, deltaAfters ) (a19 -> c7) (a18 -> c6) destructor (a17 -> List Alert -> List Feedback -> ( ControlFns input7 state7 delta9 output7, restFns6 ) -> ( State state7, restStates7 ) -> List Feedback) (a16 -> List Alert -> Basics.Int -> ( ControlFns input6 state6 delta8 output6, restFns5 ) -> ( State state6, restStates6 ) -> List Alert) (Path -> a15 -> c5) (a14 -> Basics.Int -> ( ControlFns input5 state5 delta7 output5, restFns4 ) -> ( State state5, restStates5 ) -> ( State state5, restStates5 )) (Path -> a13 -> c4) (Path -> a12 -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> ( delta6 -> delta1_2, restDeltaSetters2 ) -> ( Platform.Cmd.Cmd delta6, restDeltas1 ) -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> ( ( value, after ) -> delta5, befores ) -> ( after, afters ) -> ( value -> delta5, next )) (a9 -> { controlFns : ( ControlFns input4 state1_1 delta4 output4, restControlFns ), deltaSetters : ( Delta delta4 -> tagDelta, restDeltaSetters1 ), finalTagStates : ( finalTagState, nextFinalTagState ) -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : ( (input4 -> ( State tagStates1, Platform.Cmd.Cmd (Delta tagDelta) )) -> finalTagState, restInputTuplizers ), maybeOverridesAfter : ( maybeOverrideAfter, restMaybeOverridesAfter ), maybeOverridesBefore : ( ( Maybe (State state1_1), maybeOverrideAfter ) -> ( Maybe (State state4), restMaybeStates ), restMaybeOverridesBefore ), tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> ( ControlFns input3 state3 delta3 output3, restFns3 ) -> ( State state3, restStates3 ) -> Result (List Feedback) output3) ( Maybe a7, stateAfter ) ( stateAfter, stateAfters ) (a6 -> c2) (a5 -> c1) (a4 -> Basics.Int -> Basics.Int -> (( State argState, restArgStates ) -> tagStates) -> ( Maybe (State argState), restMaybeArgStates ) -> ( State argState, restArgStates ) -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> ( Delta delta2 -> delta1_1, restSetters1 ) -> ( ControlFns input2 state2 delta2 output2, restFns2 ) -> ( State state2, restStates2 ) -> List (Platform.Sub.Sub delta1_1)) (a2 -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : ( State state1, restStates1 ) -> recordState0 } -> ( ControlFns input1 state1 delta1 output1, restFns1 ) -> ( Delta delta1 -> recordDelta, restDeltaSetters ) -> ( Delta delta1, restDeltas ) -> ( State state1, restStates1 ) -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> ( ControlFns input state e output, restFns ) -> ( Delta e -> delta, restSetters ) -> ( State state, restStates ) -> List (Subcontrol delta))

Add a tag with two arguments to a custom type.

type Point
    = Point Float Float

pointControl =
    customType
        (\point tag ->
            case tag of
                Point x y ->
                    point x y
        )
        |> tag2 "Point" Point float float

tag3 : String -> (output12 -> output11 -> output10 -> output9) -> AdvancedControl output12 state11 delta15 output12 -> AdvancedControl output11 state10 delta14 output11 -> AdvancedControl output10 state9 delta13 output10 -> CustomTypeBuilder (a21 -> destructor1 -> restInputToStateConverters -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> restFns7 -> restStates8 -> List Alert) deltaAfter deltaAfters (( Delta delta14_1, a19 ) -> c7) (( ( Delta delta14_1, a19 ) -> c7, a18 ) -> c6) destructor (a17 -> List Alert -> List Feedback -> restFns6 -> restStates7 -> List Feedback) (a16 -> List Alert -> Basics.Int -> restFns5 -> restStates6 -> List Alert) (Path -> ( ControlFns ( output12, ( output11, ( output10, b ) ) ) ( State state11, ( State state10, ( State state9, End ) ) ) ( Delta delta15, ( Delta delta14, ( Delta delta13, End ) ) ) output9, a15 ) -> c5) (a14 -> Basics.Int -> restFns4 -> restStates5 -> restStates5) (Path -> ( Platform.Cmd.Cmd (Delta ( Delta delta15, ( Delta delta14, ( Delta delta13, End ) ) )), a13 ) -> c4) (Path -> ( State ( State state11, ( State state10, ( State state9, End ) ) ), a12 ) -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> restDeltaSetters2 -> restDeltas1 -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> befores -> afters -> next) (a9 -> { controlFns : restControlFns, deltaSetters : restDeltaSetters1, finalTagStates : nextFinalTagState -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : restInputTuplizers, maybeOverridesAfter : restMaybeOverridesAfter, maybeOverridesBefore : restMaybeOverridesBefore, tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> restFns3 -> restStates3 -> Result (List Feedback) output3) stateAfter stateAfters (( Maybe a23, a6 ) -> c2) (( ( Maybe a23, a6 ) -> c2, a5 ) -> c1) (a4 -> Basics.Int -> Basics.Int -> (restArgStates -> tagStates) -> restMaybeArgStates -> restArgStates -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> restSetters1 -> restFns2 -> restStates2 -> List (Platform.Sub.Sub delta1_1)) (( (( d, ( f, ( g, End ) ) ) -> h) -> d -> f -> g -> h, a2 ) -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : restStates1 -> recordState0 } -> restFns1 -> restDeltaSetters -> restDeltas -> restStates1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> restFns -> restSetters -> restStates -> List (Subcontrol delta)) -> CustomTypeBuilder (a21 -> (inputToStateConverter -> destructor1) -> ( inputToStateConverter, restInputToStateConverters ) -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> ( ControlFns input8 state8 delta11 output8, restFns7 ) -> ( State state8, restStates8 ) -> List Alert) ( Delta delta10, deltaAfter ) ( deltaAfter, deltaAfters ) (a19 -> c7) (a18 -> c6) destructor (a17 -> List Alert -> List Feedback -> ( ControlFns input7 state7 delta9 output7, restFns6 ) -> ( State state7, restStates7 ) -> List Feedback) (a16 -> List Alert -> Basics.Int -> ( ControlFns input6 state6 delta8 output6, restFns5 ) -> ( State state6, restStates6 ) -> List Alert) (Path -> a15 -> c5) (a14 -> Basics.Int -> ( ControlFns input5 state5 delta7 output5, restFns4 ) -> ( State state5, restStates5 ) -> ( State state5, restStates5 )) (Path -> a13 -> c4) (Path -> a12 -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> ( delta6 -> delta1_2, restDeltaSetters2 ) -> ( Platform.Cmd.Cmd delta6, restDeltas1 ) -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> ( ( value, after ) -> delta5, befores ) -> ( after, afters ) -> ( value -> delta5, next )) (a9 -> { controlFns : ( ControlFns input4 state1_1 delta4 output4, restControlFns ), deltaSetters : ( Delta delta4 -> tagDelta, restDeltaSetters1 ), finalTagStates : ( finalTagState, nextFinalTagState ) -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : ( (input4 -> ( State tagStates1, Platform.Cmd.Cmd (Delta tagDelta) )) -> finalTagState, restInputTuplizers ), maybeOverridesAfter : ( maybeOverrideAfter, restMaybeOverridesAfter ), maybeOverridesBefore : ( ( Maybe (State state1_1), maybeOverrideAfter ) -> ( Maybe (State state4), restMaybeStates ), restMaybeOverridesBefore ), tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> ( ControlFns input3 state3 delta3 output3, restFns3 ) -> ( State state3, restStates3 ) -> Result (List Feedback) output3) ( Maybe a7, stateAfter ) ( stateAfter, stateAfters ) (a6 -> c2) (a5 -> c1) (a4 -> Basics.Int -> Basics.Int -> (( State argState, restArgStates ) -> tagStates) -> ( Maybe (State argState), restMaybeArgStates ) -> ( State argState, restArgStates ) -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> ( Delta delta2 -> delta1_1, restSetters1 ) -> ( ControlFns input2 state2 delta2 output2, restFns2 ) -> ( State state2, restStates2 ) -> List (Platform.Sub.Sub delta1_1)) (a2 -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : ( State state1, restStates1 ) -> recordState0 } -> ( ControlFns input1 state1 delta1 output1, restFns1 ) -> ( Delta delta1 -> recordDelta, restDeltaSetters ) -> ( Delta delta1, restDeltas ) -> ( State state1, restStates1 ) -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> ( ControlFns input state e output, restFns ) -> ( Delta e -> delta, restSetters ) -> ( State state, restStates ) -> List (Subcontrol delta))

Add a tag with three arguments to a custom type.

type Point3D
    = Point3D Float Float Float

point3DControl =
    customType
        (\point3D tag ->
            case tag of
                Point3D x y z ->
                    point3D x y z
        )
        |> tag3 "Point3D" Point3D float float float

tag4 : String -> (output13 -> output12 -> output11 -> output10 -> output9) -> AdvancedControl output13 state12 delta16 output13 -> AdvancedControl output12 state11 delta15 output12 -> AdvancedControl output11 state10 delta14 output11 -> AdvancedControl output10 state9 delta13 output10 -> CustomTypeBuilder (a21 -> destructor1 -> restInputToStateConverters -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> restFns7 -> restStates8 -> List Alert) deltaAfter deltaAfters (( Delta delta14_1, a19 ) -> c7) (( ( Delta delta14_1, a19 ) -> c7, a18 ) -> c6) destructor (a17 -> List Alert -> List Feedback -> restFns6 -> restStates7 -> List Feedback) (a16 -> List Alert -> Basics.Int -> restFns5 -> restStates6 -> List Alert) (Path -> ( ControlFns ( output13, ( output12, ( output11, ( output10, b ) ) ) ) ( State state12, ( State state11, ( State state10, ( State state9, End ) ) ) ) ( Delta delta16, ( Delta delta15, ( Delta delta14, ( Delta delta13, End ) ) ) ) output9, a15 ) -> c5) (a14 -> Basics.Int -> restFns4 -> restStates5 -> restStates5) (Path -> ( Platform.Cmd.Cmd (Delta ( Delta delta16, ( Delta delta15, ( Delta delta14, ( Delta delta13, End ) ) ) )), a13 ) -> c4) (Path -> ( State ( State state12, ( State state11, ( State state10, ( State state9, End ) ) ) ), a12 ) -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> restDeltaSetters2 -> restDeltas1 -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> befores -> afters -> next) (a9 -> { controlFns : restControlFns, deltaSetters : restDeltaSetters1, finalTagStates : nextFinalTagState -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : restInputTuplizers, maybeOverridesAfter : restMaybeOverridesAfter, maybeOverridesBefore : restMaybeOverridesBefore, tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> restFns3 -> restStates3 -> Result (List Feedback) output3) stateAfter stateAfters (( Maybe a23, a6 ) -> c2) (( ( Maybe a23, a6 ) -> c2, a5 ) -> c1) (a4 -> Basics.Int -> Basics.Int -> (restArgStates -> tagStates) -> restMaybeArgStates -> restArgStates -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> restSetters1 -> restFns2 -> restStates2 -> List (Platform.Sub.Sub delta1_1)) (( (( d, ( f, ( g, ( h, End ) ) ) ) -> i) -> d -> f -> g -> h -> i, a2 ) -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : restStates1 -> recordState0 } -> restFns1 -> restDeltaSetters -> restDeltas -> restStates1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> restFns -> restSetters -> restStates -> List (Subcontrol delta)) -> CustomTypeBuilder (a21 -> (inputToStateConverter -> destructor1) -> ( inputToStateConverter, restInputToStateConverters ) -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> ( ControlFns input8 state8 delta11 output8, restFns7 ) -> ( State state8, restStates8 ) -> List Alert) ( Delta delta10, deltaAfter ) ( deltaAfter, deltaAfters ) (a19 -> c7) (a18 -> c6) destructor (a17 -> List Alert -> List Feedback -> ( ControlFns input7 state7 delta9 output7, restFns6 ) -> ( State state7, restStates7 ) -> List Feedback) (a16 -> List Alert -> Basics.Int -> ( ControlFns input6 state6 delta8 output6, restFns5 ) -> ( State state6, restStates6 ) -> List Alert) (Path -> a15 -> c5) (a14 -> Basics.Int -> ( ControlFns input5 state5 delta7 output5, restFns4 ) -> ( State state5, restStates5 ) -> ( State state5, restStates5 )) (Path -> a13 -> c4) (Path -> a12 -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> ( delta6 -> delta1_2, restDeltaSetters2 ) -> ( Platform.Cmd.Cmd delta6, restDeltas1 ) -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> ( ( value, after ) -> delta5, befores ) -> ( after, afters ) -> ( value -> delta5, next )) (a9 -> { controlFns : ( ControlFns input4 state1_1 delta4 output4, restControlFns ), deltaSetters : ( Delta delta4 -> tagDelta, restDeltaSetters1 ), finalTagStates : ( finalTagState, nextFinalTagState ) -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : ( (input4 -> ( State tagStates1, Platform.Cmd.Cmd (Delta tagDelta) )) -> finalTagState, restInputTuplizers ), maybeOverridesAfter : ( maybeOverrideAfter, restMaybeOverridesAfter ), maybeOverridesBefore : ( ( Maybe (State state1_1), maybeOverrideAfter ) -> ( Maybe (State state4), restMaybeStates ), restMaybeOverridesBefore ), tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> ( ControlFns input3 state3 delta3 output3, restFns3 ) -> ( State state3, restStates3 ) -> Result (List Feedback) output3) ( Maybe a7, stateAfter ) ( stateAfter, stateAfters ) (a6 -> c2) (a5 -> c1) (a4 -> Basics.Int -> Basics.Int -> (( State argState, restArgStates ) -> tagStates) -> ( Maybe (State argState), restMaybeArgStates ) -> ( State argState, restArgStates ) -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> ( Delta delta2 -> delta1_1, restSetters1 ) -> ( ControlFns input2 state2 delta2 output2, restFns2 ) -> ( State state2, restStates2 ) -> List (Platform.Sub.Sub delta1_1)) (a2 -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : ( State state1, restStates1 ) -> recordState0 } -> ( ControlFns input1 state1 delta1 output1, restFns1 ) -> ( Delta delta1 -> recordDelta, restDeltaSetters ) -> ( Delta delta1, restDeltas ) -> ( State state1, restStates1 ) -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> ( ControlFns input state e output, restFns ) -> ( Delta e -> delta, restSetters ) -> ( State state, restStates ) -> List (Subcontrol delta))

Add a tag with four arguments to a custom type.

tag5 : String -> (output14 -> output13 -> output12 -> output11 -> output10 -> output9) -> AdvancedControl output14 state13 delta17 output14 -> AdvancedControl output13 state12 delta16 output13 -> AdvancedControl output12 state11 delta15 output12 -> AdvancedControl output11 state10 delta14 output11 -> AdvancedControl output10 state9 delta13 output10 -> CustomTypeBuilder (a21 -> destructor1 -> restInputToStateConverters -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> restFns7 -> restStates8 -> List Alert) deltaAfter deltaAfters (( Delta delta14_1, a19 ) -> c7) (( ( Delta delta14_1, a19 ) -> c7, a18 ) -> c6) destructor (a17 -> List Alert -> List Feedback -> restFns6 -> restStates7 -> List Feedback) (a16 -> List Alert -> Basics.Int -> restFns5 -> restStates6 -> List Alert) (Path -> ( ControlFns ( output14, ( output13, ( output12, ( output11, ( output10, b ) ) ) ) ) ( State state13, ( State state12, ( State state11, ( State state10, ( State state9, End ) ) ) ) ) ( Delta delta17, ( Delta delta16, ( Delta delta15, ( Delta delta14, ( Delta delta13, End ) ) ) ) ) output9, a15 ) -> c5) (a14 -> Basics.Int -> restFns4 -> restStates5 -> restStates5) (Path -> ( Platform.Cmd.Cmd (Delta ( Delta delta17, ( Delta delta16, ( Delta delta15, ( Delta delta14, ( Delta delta13, End ) ) ) ) )), a13 ) -> c4) (Path -> ( State ( State state13, ( State state12, ( State state11, ( State state10, ( State state9, End ) ) ) ) ), a12 ) -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> restDeltaSetters2 -> restDeltas1 -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> befores -> afters -> next) (a9 -> { controlFns : restControlFns, deltaSetters : restDeltaSetters1, finalTagStates : nextFinalTagState -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : restInputTuplizers, maybeOverridesAfter : restMaybeOverridesAfter, maybeOverridesBefore : restMaybeOverridesBefore, tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> restFns3 -> restStates3 -> Result (List Feedback) output3) stateAfter stateAfters (( Maybe a23, a6 ) -> c2) (( ( Maybe a23, a6 ) -> c2, a5 ) -> c1) (a4 -> Basics.Int -> Basics.Int -> (restArgStates -> tagStates) -> restMaybeArgStates -> restArgStates -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> restSetters1 -> restFns2 -> restStates2 -> List (Platform.Sub.Sub delta1_1)) (( (( d, ( f, ( g, ( h, ( i, End ) ) ) ) ) -> j) -> d -> f -> g -> h -> i -> j, a2 ) -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : restStates1 -> recordState0 } -> restFns1 -> restDeltaSetters -> restDeltas -> restStates1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> restFns -> restSetters -> restStates -> List (Subcontrol delta)) -> CustomTypeBuilder (a21 -> (inputToStateConverter -> destructor1) -> ( inputToStateConverter, restInputToStateConverters ) -> tag -> ( State tagStates2, Platform.Cmd.Cmd delta12 )) (a20 -> List Alert -> ( ControlFns input8 state8 delta11 output8, restFns7 ) -> ( State state8, restStates8 ) -> List Alert) ( Delta delta10, deltaAfter ) ( deltaAfter, deltaAfters ) (a19 -> c7) (a18 -> c6) destructor (a17 -> List Alert -> List Feedback -> ( ControlFns input7 state7 delta9 output7, restFns6 ) -> ( State state7, restStates7 ) -> List Feedback) (a16 -> List Alert -> Basics.Int -> ( ControlFns input6 state6 delta8 output6, restFns5 ) -> ( State state6, restStates6 ) -> List Alert) (Path -> a15 -> c5) (a14 -> Basics.Int -> ( ControlFns input5 state5 delta7 output5, restFns4 ) -> ( State state5, restStates5 ) -> ( State state5, restStates5 )) (Path -> a13 -> c4) (Path -> a12 -> c3) (a11 -> List (Platform.Cmd.Cmd delta1_2) -> ( delta6 -> delta1_2, restDeltaSetters2 ) -> ( Platform.Cmd.Cmd delta6, restDeltas1 ) -> List (Platform.Cmd.Cmd delta1_2)) (a10 -> ( ( value, after ) -> delta5, befores ) -> ( after, afters ) -> ( value -> delta5, next )) (a9 -> { controlFns : ( ControlFns input4 state1_1 delta4 output4, restControlFns ), deltaSetters : ( Delta delta4 -> tagDelta, restDeltaSetters1 ), finalTagStates : ( finalTagState, nextFinalTagState ) -> restFinalTagStates, initialTagStates : ( State state4, restStates4 ), inputTuplizers : ( (input4 -> ( State tagStates1, Platform.Cmd.Cmd (Delta tagDelta) )) -> finalTagState, restInputTuplizers ), maybeOverridesAfter : ( maybeOverrideAfter, restMaybeOverridesAfter ), maybeOverridesBefore : ( ( Maybe (State state1_1), maybeOverrideAfter ) -> ( Maybe (State state4), restMaybeStates ), restMaybeOverridesBefore ), tagStateOverrider : (Basics.Int -> Basics.Int -> (End -> tagStates1) -> End -> End -> State tagStates1) -> Basics.Int -> Basics.Int -> (identity -> identity) -> ( Maybe (State state4), restMaybeStates ) -> ( State state4, restStates4 ) -> State tagStates1 } -> toFinalTagStates) (a8 -> Result (List Feedback) output3 -> Basics.Int -> ( ControlFns input3 state3 delta3 output3, restFns3 ) -> ( State state3, restStates3 ) -> Result (List Feedback) output3) ( Maybe a7, stateAfter ) ( stateAfter, stateAfters ) (a6 -> c2) (a5 -> c1) (a4 -> Basics.Int -> Basics.Int -> (( State argState, restArgStates ) -> tagStates) -> ( Maybe (State argState), restMaybeArgStates ) -> ( State argState, restArgStates ) -> State tagStates) (a3 -> List (Platform.Sub.Sub delta1_1) -> ( Delta delta2 -> delta1_1, restSetters1 ) -> ( ControlFns input2 state2 delta2 output2, restFns2 ) -> ( State state2, restStates2 ) -> List (Platform.Sub.Sub delta1_1)) (a2 -> c) (a1 -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : ( State state1, restStates1 ) -> recordState0 } -> ( ControlFns input1 state1 delta1 output1, restFns1 ) -> ( Delta delta1 -> recordDelta, restDeltaSetters ) -> ( Delta delta1, restDeltas ) -> ( State state1, restStates1 ) -> { newCmds : List (Platform.Cmd.Cmd recordDelta), newStates : recordState }) (a -> List (Subcontrol delta) -> List Alert -> ( ControlFns input state e output, restFns ) -> ( Delta e -> delta, restSetters ) -> ( State state, restStates ) -> List (Subcontrol delta))

Add a tag with five arguments to a custom type.

endCustomType : CustomTypeBuilder (((input -> ( State ( State state, restStates ), Platform.Cmd.Cmd (Delta ( Delta delta, restDeltas )) )) -> End -> input -> ( State ( State state, restStates ), Platform.Cmd.Cmd (Delta ( Delta delta, restDeltas )) )) -> (inputToStateConverter -> destructor) -> ( inputToStateConverter, restInputToStateConverters ) -> input -> ( State ( State state, restStates ), Platform.Cmd.Cmd (Delta ( Delta delta, restDeltas )) )) ((List Alert -> End -> End -> List Alert) -> List Alert -> ( ControlFns input1 state delta output1, restFns ) -> ( State state, restStates ) -> List Alert) deltaAfter afters deltaBefore (End -> befores) (inputToStateConverter -> destructor) ((List Alert -> List Feedback -> End -> End -> List Feedback) -> List Alert -> List Feedback -> ( ControlFns input1 state delta output1, restFns ) -> ( State state, restStates ) -> List Feedback) ((List Alert -> Basics.Int -> End -> End -> List Alert) -> List Alert -> Basics.Int -> ( ControlFns input1 state delta output1, restFns ) -> ( State state, restStates ) -> List Alert) (Path -> End -> ( ControlFns input1 state delta output1, restFns )) ((Basics.Int -> End -> End -> End) -> Basics.Int -> ( ControlFns input1 state delta output1, restFns ) -> ( State state, restStates ) -> ( State state, restStates )) (Path -> End -> deltas) (Path -> End -> ( State state, restStates )) ((List (Platform.Cmd.Cmd ( Delta delta, restDeltas )) -> End -> End -> List (Platform.Cmd.Cmd ( Delta delta, restDeltas ))) -> List (Platform.Cmd.Cmd ( Delta delta, restDeltas )) -> ( setter, restSetters ) -> deltas -> List (Platform.Cmd.Cmd ( Delta delta, restDeltas ))) ((End -> End -> End) -> befores -> afters -> ( setter, restSetters )) (({ c | finalTagStates : End -> b2 } -> b2) -> { controlFns : ( ControlFns input1 state delta output1, restFns ), deltaSetters : ( setter, restSetters ), finalTagStates : a1 -> a1, initialTagStates : ( State state, restStates ), inputTuplizers : g, maybeOverridesAfter : h, maybeOverridesBefore : i, tagStateOverrider : j } -> ( inputToStateConverter, restInputToStateConverters )) ((a -> b1 -> End -> End -> a) -> Result (List Feedback) value -> Basics.Int -> ( ControlFns input1 state delta output1, restFns ) -> ( State state, restStates ) -> Result (List Feedback) output) stateAfter h stateBefore (End -> i) j ((List (Platform.Sub.Sub ( Delta delta, restDeltas )) -> End -> End -> End -> List (Platform.Sub.Sub ( Delta delta, restDeltas ))) -> List (Platform.Sub.Sub ( Delta delta, restDeltas )) -> ( setter, restSetters ) -> ( ControlFns input1 state delta output1, restFns ) -> ( State state, restStates ) -> List (Platform.Sub.Sub ( Delta delta, restDeltas ))) (End -> g) (({ newCmds : List (Platform.Cmd.Cmd ( Delta delta, restDeltas )), newStates : End -> ( State state, restStates ) } -> End -> End -> End -> End -> { newCmds : List (Platform.Cmd.Cmd ( Delta delta, restDeltas )), newStates : End -> ( State state, restStates ) }) -> { newCmds : List (Platform.Cmd.Cmd ( Delta delta, restDeltas )), newStates : ( State state, restStates ) -> ( State state, restStates ) } -> ( ControlFns input1 state delta output1, restFns ) -> ( setter, restSetters ) -> ( Delta delta, restDeltas ) -> ( State state, restStates ) -> { newCmds : List (Platform.Cmd.Cmd ( Delta delta, restDeltas )), newStates : End -> ( State state, restStates ) }) ((List (Subcontrol ( Delta delta, restDeltas )) -> b -> End -> End -> End -> List (Subcontrol ( Delta delta, restDeltas ))) -> List (Subcontrol ( Delta delta, restDeltas )) -> List Alert -> ( ControlFns input1 state delta output1, restFns ) -> ( setter, restSetters ) -> ( State state, restStates ) -> List (Subcontrol ( Delta delta, restDeltas ))) -> AdvancedControl input ( State state, restStates ) ( Delta delta, restDeltas ) output

Finalise the construction of a customType combinator.

type alias Foo
    = Bar
    | Baz


helloControl =
    customType
        (\bar baz tag ->
            case tag ofcustomType
                Bar -> bar
                Baz -> baz
        )
        |> tag0 "Bar" Bar
        |> tag0 "Baz" Baz
        |> endCustomType

Form internals

These are types that you will see in your form's State and Delta type signatures.


type State state

State is the form's equivalent of an Elm program's Model type. It is used to manage the form's internal state.


type Delta delta

A Delta is the form's equivalent of an Elm program's Msg type. It is used internally within a form to update its state.


type ListDelta delta

Special Delta type used only by list controls


type End

Under the hood, this library encodes complex Elm types (such as records and custom types) as nested tuples, which are used in both the State and Delta types for each Control. The End type is used to mark the end of a nested tuple.

For example, the State for this Elm type:

type alias User =
    { name : String, age : Int }

Could be encoded as:

( String, ( Int, End ) )

Internal stuff that you can ignore

A user of this package shouldn't need to know about any of these types - they are only exposed to make it possible to write type signatures.


type AdvancedControl input state delta output

A slightly more flexible version of Control


type ControlFns input state delta output

Some internal stuff needed to build up record and custom type controls


type Alert

Some internal stuff needed to handle validations


type RecordFns input state delta output recordOutput

Some internal stuff needed to build up a record control


type Status

an internal type needed to represent the validation state of a control


type alias InternalViewConfig state =
{ state : state
, status : Status
, alerts : List Alert
, selected : Basics.Int
, name : String
, id : String
, label : String
, class : List String 
}

Some internal stuff needed to view controls


type alias Path =
Path

an internal type needed to track the position of a control within a tree of controls


type alias Feedback =
{ path : Path
, label : String
, message : String
, fail : Basics.Bool 
}

Some internal stuff to handle validation