for more information visit the package's GitHub page
Package contains the following modules:
both or only one of them
AndOr
The basic types of this package look like this:
type AndOr first second
= Both ( first, second )
| Only (Or first second)
type Or first second
= First first
| Second second
Both types can be quite useful! ...But first
AndOr
and Or
are prone to misuse, just like Maybe
, tuple, Bool
etc.
When there is a representation of your data that's more descriptive, use that instead!
Example: Modeling the result of an operation that can fail, succeed or succeed with warnings
type alias Fallible a =
AndOr a Error
This is problematic from multiple standpoints:
- Why should error and warning types be required to be the same?
- Why not have a unified case for success:
elm
type alias Fallible a =
Or { result : a, warnings : List RecoverableError }
UnrecoverableError
- Who tells you that "first" means "success" and "second" means "error"? (or the other way round?)
- Why not use descriptive names:
elm
type Fallible a
= Success { result : a, errors : List RecoverableError }
| UnrecoverableError UnrecoverableError
AndOr
and Or
are useful for generic operations where no descriptive names exist –
similar to how tuples are used for partition results because there is no information
on what each side means.
KeysSet.fold2From
which is similar to Dict.merge
but more comprehensible and easier to work with thanks to AndOr
( [], seconds ) ->
seconds
|> List.map
(\first -> Only (Or.Second first) |> combine)
( firstHead :: firstTail, secondHead :: secondTail ) ->
(AndOr.Both firstHead secondHead |> combine)
:: List.AndOr.map2 combine firstTail secondTail
- type-safe partitioning
elm
List.Or.partition : (a -> Or first second) -> (List a -> ( List first, List second ))
List.Or.partition chooseSide list =
case list of
[] ->
[]
head :: tail ->
let
consHead : ( List first, List second ) -> ( List first, List second )
consHead =
case head |> chooseSide of
First first ->
And.firstMap ((::) first)
Second second ->
And.secondMap ((::) second)
in
tail |> List.Or.partition chooseSide |> consHead
```
AndOr
All of them don't separate out the "only one of both" case.
Or
kingwither/elmeither
toastal/either
voidLeft
for setting, singleton
for Right
etc.Data.Either
All of them use Left
and Right
as variant names whereas Or
's First
and Second
are consistent with elm's tuple part names.
The API is pretty slim, only covering the needs I could think of. If you have an idea for a useful helper → contribute