Fantasy Land -compliant Either type
npm install sanctuary-eitherThe Either type represents values with two possibilities: a value of typeEither a b is either a Left whose value is of type a or a Right whose
value is of type b.
Either a b satisfies the following [Fantasy Land][] specifications:
``javascript
> const Useless = require ('sanctuary-useless')
> const isTypeClass = x =>
. type (x) === 'sanctuary-type-classes/TypeClass@1'
> S.map (k => k + ' '.repeat (16 - k.length) +
. (Z[k].test (Right (Useless)) ? '\u2705 ' :
. Z[k].test (Right (['foo'])) ? '\u2705 * ' :
. / otherwise / '\u274C '))
. (S.keys (S.unchecked.filter (isTypeClass) (Z)))
[ 'Setoid ✅ * ', // if ‘a’ and ‘b’ satisfy Setoid
. 'Ord ✅ * ', // if ‘a’ and ‘b’ satisfy Ord
. 'Semigroupoid ❌ ',
. 'Category ❌ ',
. 'Semigroup ✅ * ', // if ‘a’ and ‘b’ satisfy Semigroup
. 'Monoid ❌ ',
. 'Group ❌ ',
. 'Filterable ❌ ',
. 'Functor ✅ ',
. 'Bifunctor ✅ ',
. 'Profunctor ❌ ',
. 'Apply ✅ ',
. 'Applicative ✅ ',
. 'Chain ✅ ',
. 'ChainRec ✅ ',
. 'Monad ✅ ',
. 'Alt ✅ ',
. 'Plus ❌ ',
. 'Alternative ❌ ',
. 'Foldable ✅ ',
. 'Traversable ✅ ',
. 'Extend ✅ ',
. 'Comonad ❌ ',
. 'Contravariant ❌ ' ]
`
Either [type representative][].
#### Either.Left :: a -> Either a b
Constructs a value of type Either a b from a value of type a.
`javascript`
> Left ('sqrt undefined for -1')
Left ('sqrt undefined for -1')
#### Either.Right :: b -> Either a b
Constructs a value of type Either a b from a value of type b.
`javascript`
> Right (42)
Right (42)
#### Either.fantasy-land/of :: b -> Either a b
- of (Either) (x) is equivalent to Right (x)
`javascript`
> S.of (Either) (42)
Right (42)
#### Either.fantasy-land/chainRec :: ((a -> c, b -> c, a) -> Either d c, a) -> Either d b
`javascript
> Z.chainRec (
. Either,
. (next, done, x) =>
. x <= 1 ? Left ('!!') : Right (x >= 1000 ? done (x) : next (x * x)),
. 1
. )
Left ('!!')
> Z.chainRec (
. Either,
. (next, done, x) =>
. x <= 1 ? Left ('!!') : Right (x >= 1000 ? done (x) : next (x * x)),
. 2
. )
Right (65536)
`
#### Either#@@show :: (Showable a, Showable b) => Either a b ~> () -> String
- show (Left (x)) is equivalent to 'Left (' + show (x) + ')'show (Right (x))
- is equivalent to 'Right (' + show (x) + ')'
`javascript
> show (Left ('sqrt undefined for -1'))
'Left ("sqrt undefined for -1")'
> show (Right ([1, 2, 3]))
'Right ([1, 2, 3])'
`
#### Either#fantasy-land/equals :: (Setoid a, Setoid b) => Either a b ~> Either a b -> Boolean
- Left (x) is equal to Left (y) [iff][] x is equal to yZ.equals
according to [][]Right (x)
- is equal to Right (y) [iff][] x is equal to yZ.equals
according to [][]Left (x)
- is never equal to Right (y)
`javascript
> S.equals (Left ([1, 2, 3])) (Left ([1, 2, 3]))
true
> S.equals (Right ([1, 2, 3])) (Right ([1, 2, 3]))
true
> S.equals (Left ([1, 2, 3])) (Right ([1, 2, 3]))
false
`
#### Either#fantasy-land/lte :: (Ord a, Ord b) => Either a b ~> Either a b -> Boolean
- Left (x) is less than or equal to Left (y) [iff][] x is lessy
than or equal to according to [Z.lte][]Right (x)
- is less than or equal to Right (y) [iff][] x is lessy
than or equal to according to [Z.lte][]Left (x)
- is always less than Right (y)
`javascript
> S.filter (S.lte (Left (1))) ([Left (0), Left (1), Left (2)])
[Left (0), Left (1)]
> S.filter (S.lte (Right (1))) ([Right (0), Right (1), Right (2)])
[Right (0), Right (1)]
> S.filter (S.lte (Left (1))) ([Right (0), Right (1), Right (2)])
[]
> S.filter (S.lte (Right (1))) ([Left (0), Left (1), Left (2)])
[Left (0), Left (1), Left (2)]
`
#### Either#fantasy-land/concat :: (Semigroup a, Semigroup b) => Either a b ~> Either a b -> Either a b
- concat (Left (x)) (Left (y)) is equivalent toLeft (concat (x) (y))
concat (Right (x)) (Right (y))
- is equivalent toRight (concat (x) (y))
concat (Left (x)) (Right (y))
- is equivalent to Right (y)concat (Right (x)) (Left (y))
- is equivalent to Right (x)
`javascript
> S.concat (Left ('abc')) (Left ('def'))
Left ('abcdef')
> S.concat (Right ([1, 2, 3])) (Right ([4, 5, 6]))
Right ([1, 2, 3, 4, 5, 6])
> S.concat (Left ('abc')) (Right ([1, 2, 3]))
Right ([1, 2, 3])
> S.concat (Right ([1, 2, 3])) (Left ('abc'))
Right ([1, 2, 3])
`
#### Either#fantasy-land/map :: Either a b ~> (b -> c) -> Either a c
- map (f) (Left (x)) is equivalent to Left (x)map (f) (Right (x))
- is equivalent to Right (f (x))
`javascript
> S.map (S.add (1)) (Left ('sqrt undefined for -1'))
Left ('sqrt undefined for -1')
> S.map (S.add (1)) (Right (99))
Right (100)
`
#### Either#fantasy-land/bimap :: Either a c ~> (a -> b, c -> d) -> Either b d
- bimap (f) (g) (Left (x)) is equivalent to Left (f (x))bimap (f) (g) (Right (x))
- is equivalent to Right (g (x))
`javascript
> S.bimap (S.toUpper) (S.add (1)) (Left ('abc'))
Left ('ABC')
> S.bimap (S.toUpper) (S.add (1)) (Right (99))
Right (100)
`
#### Either#fantasy-land/ap :: Either a b ~> Either a (b -> c) -> Either a c
- ap (Left (x)) (Left (y)) is equivalent to Left (x)ap (Left (x)) (Right (y))
- is equivalent to Left (x)ap (Right (f)) (Left (x))
- is equivalent to Left (x)ap (Right (f)) (Right (x))
- is equivalent to Right (f (x))
`javascript
> S.ap (Left ('div undefined for 0')) (Left ('sqrt undefined for -1'))
Left ('div undefined for 0')
> S.ap (Left ('div undefined for 0')) (Right (99))
Left ('div undefined for 0')
> S.ap (Right (S.add (1))) (Left ('sqrt undefined for -1'))
Left ('sqrt undefined for -1')
> S.ap (Right (S.add (1))) (Right (99))
Right (100)
`
#### Either#fantasy-land/chain :: Either a b ~> (b -> Either a c) -> Either a c
- chain (f) (Left (x)) is equivalent to Left (x)chain (f) (Right (x))
- is equivalent to f (x)
`javascript
> const sqrt = n => n < 0 ? Left ('sqrt undefined for ' + show (n))
. : Right (Math.sqrt (n))
> S.chain (sqrt) (Left ('div undefined for 0'))
Left ('div undefined for 0')
> S.chain (sqrt) (Right (-1))
Left ('sqrt undefined for -1')
> S.chain (sqrt) (Right (25))
Right (5)
`
#### Either#fantasy-land/alt :: Either a b ~> Either a b -> Either a b
- alt (Left (y)) (Left (x)) is equivalent to Left (y)alt (Right (y)) (Left (x))
- is equivalent to Right (y)alt (Left (y)) (Right (x))
- is equivalent to Right (x)alt (Right (y)) (Right (x))
- is equivalent to Right (x)
`javascript
> S.alt (Left ('B')) (Left ('A'))
Left ('B')
> S.alt (Right (1)) (Left ('C'))
Right (1)
> S.alt (Left ('D')) (Right (2))
Right (2)
> S.alt (Right (4)) (Right (3))
Right (3)
`
#### Either#fantasy-land/reduce :: Either a b ~> ((c, b) -> c, c) -> c
- reduce (f) (x) (Left (y)) is equivalent to xreduce (f) (x) (Right (y))
- is equivalent to f (x) (y)
`javascript
> S.reduce (S.concat) ([1]) (Left ('sqrt undefined for -1'))
[1]
> S.reduce (S.concat) ([1]) (Right ([2]))
[1, 2]
`
- traverse (A) (f) (Left (x)) is equivalent to of (A) (Left (x))traverse (A) (f) (Right (x))
- is equivalent to map (Right) (f (x))
`javascript
> S.traverse (Array) (S.words) (Left ('sqrt undefined for -1'))
[Left ('sqrt undefined for -1')]
> S.traverse (Array) (S.words) (Right ('foo bar baz'))
[Right ('foo'), Right ('bar'), Right ('baz')]
`
#### Either#fantasy-land/extend :: Either a b ~> (Either a b -> c) -> Either a c
- extend (f) (Left (x)) is equivalent to Left (x)extend (f) (Right (x))
- is equivalent to Right (f (Right (x)))
`javascript
> S.extend (S.reduce (S.add) (1)) (Left ('sqrt undefined for -1'))
Left ('sqrt undefined for -1')
> S.extend (S.reduce (S.add) (1)) (Right (99))
Right (100)
`
[Fantasy Land]: https://github.com/fantasyland/fantasy-land/tree/v4.0.1
[Z.equals]: https://github.com/sanctuary-js/sanctuary-type-classes/tree/v12.1.0#equalsZ.lte`]: https://github.com/sanctuary-js/sanctuary-type-classes/tree/v12.1.0#lte
[
[iff]: https://en.wikipedia.org/wiki/If_and_only_if
[type representative]: https://github.com/fantasyland/fantasy-land/tree/v4.0.1#type-representatives