Skip to content

Match multiple unions simultaneously #63

@OliverJAsh

Description

@OliverJAsh

In Elm you can match against multiple types at once, by storing them in a tuple and then matching against that:

type Action = AgreeToTerms | AddFiles { files : List File }
type State = Onboarding | Form { files : List File }

myMatch : Action -> State -> State
myMatch action state = case ( action, state ) of
  ( AgreeToTerms, Onboarding ) ->
    Form { files = [] }
  ( AddFiles { files }, Form form ) ->
    Form { files = form.files }
  ( _ , _ ) ->
    state

Full example: https://github.com/rtfeldman/elm-spa-example/blob/17a3398623f9e538f14f5b0d039fd62b3beae934/src/Main.elm#L210

Currently, if we want to do the same via Unionize, the best we can do is nesting matchs:

const Action = unionize({
    AgreeToTerms: ofType<{}>(),
    AddFiles: ofType<{ files: File[] }>(),
});
type Action = UnionOf<typeof Action>;

const State = unionize({
    Onboarding: ofType<{}>(),
    Form: ofType<{ files: File[] }>(),
});
type State = UnionOf<typeof State>;

const myMatch = (action: Action) => (state: State) =>
    Action.match({
        AgreeToTerms: () =>
            State.match({
                Onboarding: () => State.Form({ files: [] }),
                default: () => state,
            })(state),
        AddFiles: ({ files }) =>
            State.match({
                Form: form => State.Form({ files: form.files.concat(files) }),
                default: () => state,
            })(state),
        default: () => state,
    })(action);

It would be amazing if we could somehow provide a syntax for matching mutliple unions simultaneously. Pseudo code:

const myMatch = match([Action, State])([
    [[['AgreeToTerms', 'Onboarding']], () =>
        State.Form({ files: [] })
    ],
    [['AddFiles', 'Form'], ({ files }, form) =>
        State.Form({ files: form.files.concat(files) })
    ],
    [['default', 'default'], (_, state) =>
        state
    ]
])

I have no idea if that would be possible with TS, though. WDYT?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions