|
| 1 | +<a href="https://github.com/fantasyland/fantasy-land"><img alt="Fantasy Land" src="https://raw.githubusercontent.com/fantasyland/fantasy-land/master/logo.png" width="75" height="75" align="left"></a> |
| 2 | + |
| 3 | +# sanctuary-either |
| 4 | + |
| 5 | +The Either type represents values with two possibilities: a value of type |
| 6 | +`Either a b` is either a Left whose value is of type `a` or a Right whose |
| 7 | +value is of type `b`. |
| 8 | + |
| 9 | +`Either a b` satisfies the following [Fantasy Land][] specifications: |
| 10 | + |
| 11 | +```javascript |
| 12 | +> const Useless = require ('sanctuary-useless') |
| 13 | + |
| 14 | +> S.map (k => k + ' '.repeat (16 - k.length) + |
| 15 | +. (Z[k].test (Right (Useless)) ? '\u2705 ' : |
| 16 | +. Z[k].test (Right (['foo'])) ? '\u2705 * ' : |
| 17 | +. /* otherwise */ '\u274C ')) |
| 18 | +. (S.keys (Z.filter ($.test ([]) ($.TypeClass), Z))) |
| 19 | +[ 'Setoid ✅ * ', // if ‘a’ and ‘b’ satisfy Setoid |
| 20 | +. 'Ord ✅ * ', // if ‘a’ and ‘b’ satisfy Ord |
| 21 | +. 'Semigroupoid ❌ ', |
| 22 | +. 'Category ❌ ', |
| 23 | +. 'Semigroup ✅ * ', // if ‘a’ and ‘b’ satisfy Semigroup |
| 24 | +. 'Monoid ❌ ', |
| 25 | +. 'Group ❌ ', |
| 26 | +. 'Filterable ❌ ', |
| 27 | +. 'Functor ✅ ', |
| 28 | +. 'Bifunctor ✅ ', |
| 29 | +. 'Profunctor ❌ ', |
| 30 | +. 'Apply ✅ ', |
| 31 | +. 'Applicative ✅ ', |
| 32 | +. 'Chain ✅ ', |
| 33 | +. 'ChainRec ✅ ', |
| 34 | +. 'Monad ✅ ', |
| 35 | +. 'Alt ✅ ', |
| 36 | +. 'Plus ❌ ', |
| 37 | +. 'Alternative ❌ ', |
| 38 | +. 'Foldable ✅ ', |
| 39 | +. 'Traversable ✅ ', |
| 40 | +. 'Extend ✅ ', |
| 41 | +. 'Comonad ❌ ', |
| 42 | +. 'Contravariant ❌ ' ] |
| 43 | +``` |
| 44 | + |
| 45 | +#### <a name="Either" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L138">`Either :: TypeRep Either`</a> |
| 46 | + |
| 47 | +Either [type representative][]. |
| 48 | + |
| 49 | +#### <a name="Either.Left" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L142">`Either.Left :: a -> Either a b`</a> |
| 50 | + |
| 51 | +Constructs a value of type `Either a b` from a value of type `a`. |
| 52 | + |
| 53 | +```javascript |
| 54 | +> Left ('sqrt undefined for -1') |
| 55 | +Left ('sqrt undefined for -1') |
| 56 | +``` |
| 57 | + |
| 58 | +#### <a name="Either.Right" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L165">`Either.Right :: b -> Either a b`</a> |
| 59 | + |
| 60 | +Constructs a value of type `Either a b` from a value of type `b`. |
| 61 | + |
| 62 | +```javascript |
| 63 | +> Right (42) |
| 64 | +Right (42) |
| 65 | +``` |
| 66 | + |
| 67 | +#### <a name="Either.@@type" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L188">`Either.@@type :: String`</a> |
| 68 | + |
| 69 | +Either [type identifier][]. |
| 70 | + |
| 71 | +```javascript |
| 72 | +> type (Right (42)) |
| 73 | +'sanctuary-either/Either@1' |
| 74 | + |
| 75 | +> type.parse (type (Right (42))) |
| 76 | +{namespace: 'sanctuary-either', name: 'Either', version: 1} |
| 77 | +``` |
| 78 | + |
| 79 | +#### <a name="Either.fantasy-land/of" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L201">`Either.fantasy-land/of :: b -> Either a b`</a> |
| 80 | + |
| 81 | + - `of (Either) (x)` is equivalent to `Right (x)` |
| 82 | + |
| 83 | +```javascript |
| 84 | +> S.of (Either) (42) |
| 85 | +Right (42) |
| 86 | +``` |
| 87 | + |
| 88 | +#### <a name="Either.fantasy-land/chainRec" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L214">`Either.fantasy-land/chainRec :: ((a -> c, b -> c, a) -> Either d c, a) -> Either d b`</a> |
| 89 | + |
| 90 | +```javascript |
| 91 | +> Z.chainRec ( |
| 92 | +. Either, |
| 93 | +. (next, done, x) => |
| 94 | +. x <= 1 ? Left ('!!') : Right (x >= 1000 ? done (x) : next (x * x)), |
| 95 | +. 1 |
| 96 | +. ) |
| 97 | +Left ('!!') |
| 98 | + |
| 99 | +> Z.chainRec ( |
| 100 | +. Either, |
| 101 | +. (next, done, x) => |
| 102 | +. x <= 1 ? Left ('!!') : Right (x >= 1000 ? done (x) : next (x * x)), |
| 103 | +. 2 |
| 104 | +. ) |
| 105 | +Right (65536) |
| 106 | +``` |
| 107 | + |
| 108 | +#### <a name="Either.prototype.@@show" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L243">`Either#@@show :: (Showable a, Showable b) => Either a b ~> () -> String`</a> |
| 109 | + |
| 110 | + - `show (Left (x))` is equivalent to `'Left (' + show (x) + ')'` |
| 111 | + - `show (Right (x))` is equivalent to `'Right (' + show (x) + ')'` |
| 112 | + |
| 113 | +```javascript |
| 114 | +> show (Left ('sqrt undefined for -1')) |
| 115 | +'Left ("sqrt undefined for -1")' |
| 116 | + |
| 117 | +> show (Right ([1, 2, 3])) |
| 118 | +'Right ([1, 2, 3])' |
| 119 | +``` |
| 120 | + |
| 121 | +#### <a name="Either.prototype.fantasy-land/equals" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L262">`Either#fantasy-land/equals :: (Setoid a, Setoid b) => Either a b ~> Either a b -> Boolean`</a> |
| 122 | + |
| 123 | + - `Left (x)` is equal to `Left (y)` [iff][] `x` is equal to `y` |
| 124 | + according to [`Z.equals`][] |
| 125 | + - `Right (x)` is equal to `Right (y)` [iff][] `x` is equal to `y` |
| 126 | + according to [`Z.equals`][] |
| 127 | + - `Left (x)` is never equal to `Right (y)` |
| 128 | + |
| 129 | +```javascript |
| 130 | +> S.equals (Left ([1, 2, 3])) (Left ([1, 2, 3])) |
| 131 | +true |
| 132 | + |
| 133 | +> S.equals (Right ([1, 2, 3])) (Right ([1, 2, 3])) |
| 134 | +true |
| 135 | + |
| 136 | +> S.equals (Left ([1, 2, 3])) (Right ([1, 2, 3])) |
| 137 | +false |
| 138 | +``` |
| 139 | + |
| 140 | +#### <a name="Either.prototype.fantasy-land/lte" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L287">`Either#fantasy-land/lte :: (Ord a, Ord b) => Either a b ~> Either a b -> Boolean`</a> |
| 141 | + |
| 142 | + - `Left (x)` is less than or equal to `Left (y)` [iff][] `x` is less |
| 143 | + than or equal to `y` according to [`Z.lte`][] |
| 144 | + - `Right (x)` is less than or equal to `Right (y)` [iff][] `x` is less |
| 145 | + than or equal to `y` according to [`Z.lte`][] |
| 146 | + - `Left (x)` is always less than `Right (y)` |
| 147 | + |
| 148 | +```javascript |
| 149 | +> S.filter (S.lte (Left (1))) ([Left (0), Left (1), Left (2)]) |
| 150 | +[Left (0), Left (1)] |
| 151 | + |
| 152 | +> S.filter (S.lte (Right (1))) ([Right (0), Right (1), Right (2)]) |
| 153 | +[Right (0), Right (1)] |
| 154 | + |
| 155 | +> S.filter (S.lte (Left (1))) ([Right (0), Right (1), Right (2)]) |
| 156 | +[] |
| 157 | + |
| 158 | +> S.filter (S.lte (Right (1))) ([Left (0), Left (1), Left (2)]) |
| 159 | +[Left (0), Left (1), Left (2)] |
| 160 | +``` |
| 161 | + |
| 162 | +#### <a name="Either.prototype.fantasy-land/concat" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L315">`Either#fantasy-land/concat :: (Semigroup a, Semigroup b) => Either a b ~> Either a b -> Either a b`</a> |
| 163 | + |
| 164 | + - `concat (Left (x)) (Left (y))` is equivalent to |
| 165 | + `Left (concat (x) (y))` |
| 166 | + - `concat (Right (x)) (Right (y))` is equivalent to |
| 167 | + `Right (concat (x) (y))` |
| 168 | + - `concat (Left (x)) (Right (y))` is equivalent to `Right (y)` |
| 169 | + - `concat (Right (x)) (Left (y))` is equivalent to `Right (x)` |
| 170 | + |
| 171 | +```javascript |
| 172 | +> S.concat (Left ('abc')) (Left ('def')) |
| 173 | +Left ('abcdef') |
| 174 | + |
| 175 | +> S.concat (Right ([1, 2, 3])) (Right ([4, 5, 6])) |
| 176 | +Right ([1, 2, 3, 4, 5, 6]) |
| 177 | + |
| 178 | +> S.concat (Left ('abc')) (Right ([1, 2, 3])) |
| 179 | +Right ([1, 2, 3]) |
| 180 | + |
| 181 | +> S.concat (Right ([1, 2, 3])) (Left ('abc')) |
| 182 | +Right ([1, 2, 3]) |
| 183 | +``` |
| 184 | + |
| 185 | +#### <a name="Either.prototype.fantasy-land/map" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L344">`Either#fantasy-land/map :: Either a b ~> (b -> c) -> Either a c`</a> |
| 186 | + |
| 187 | + - `map (f) (Left (x))` is equivalent to `Left (x)` |
| 188 | + - `map (f) (Right (x))` is equivalent to `Right (f (x))` |
| 189 | + |
| 190 | +```javascript |
| 191 | +> S.map (S.add (1)) (Left ('sqrt undefined for -1')) |
| 192 | +Left ('sqrt undefined for -1') |
| 193 | + |
| 194 | +> S.map (S.add (1)) (Right (99)) |
| 195 | +Right (100) |
| 196 | +``` |
| 197 | + |
| 198 | +#### <a name="Either.prototype.fantasy-land/bimap" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L363">`Either#fantasy-land/bimap :: Either a c ~> (a -> b, c -> d) -> Either b d`</a> |
| 199 | + |
| 200 | + - `bimap (f) (g) (Left (x))` is equivalent to `Left (f (x))` |
| 201 | + - `bimap (f) (g) (Right (x))` is equivalent to `Right (g (x))` |
| 202 | + |
| 203 | +```javascript |
| 204 | +> S.bimap (S.toUpper) (S.add (1)) (Left ('abc')) |
| 205 | +Left ('ABC') |
| 206 | + |
| 207 | +> S.bimap (S.toUpper) (S.add (1)) (Right (99)) |
| 208 | +Right (100) |
| 209 | +``` |
| 210 | + |
| 211 | +#### <a name="Either.prototype.fantasy-land/ap" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L382">`Either#fantasy-land/ap :: Either a b ~> Either a (b -> c) -> Either a c`</a> |
| 212 | + |
| 213 | + - `ap (Left (x)) (Left (y))` is equivalent to `Left (x)` |
| 214 | + - `ap (Left (x)) (Right (y))` is equivalent to `Left (x)` |
| 215 | + - `ap (Right (f)) (Left (x))` is equivalent to `Left (x)` |
| 216 | + - `ap (Right (f)) (Right (x))` is equivalent to `Right (f (x))` |
| 217 | + |
| 218 | +```javascript |
| 219 | +> S.ap (Left ('div undefined for 0')) (Left ('sqrt undefined for -1')) |
| 220 | +Left ('div undefined for 0') |
| 221 | + |
| 222 | +> S.ap (Left ('div undefined for 0')) (Right (99)) |
| 223 | +Left ('div undefined for 0') |
| 224 | + |
| 225 | +> S.ap (Right (S.add (1))) (Left ('sqrt undefined for -1')) |
| 226 | +Left ('sqrt undefined for -1') |
| 227 | + |
| 228 | +> S.ap (Right (S.add (1))) (Right (99)) |
| 229 | +Right (100) |
| 230 | +``` |
| 231 | + |
| 232 | +#### <a name="Either.prototype.fantasy-land/chain" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L409">`Either#fantasy-land/chain :: Either a b ~> (b -> Either a c) -> Either a c`</a> |
| 233 | + |
| 234 | + - `chain (f) (Left (x))` is equivalent to `Left (x)` |
| 235 | + - `chain (f) (Right (x))` is equivalent to `f (x)` |
| 236 | + |
| 237 | +```javascript |
| 238 | +> const sqrt = n => n < 0 ? Left ('sqrt undefined for ' + show (n)) |
| 239 | +. : Right (Math.sqrt (n)) |
| 240 | + |
| 241 | +> S.chain (sqrt) (Left ('div undefined for 0')) |
| 242 | +Left ('div undefined for 0') |
| 243 | + |
| 244 | +> S.chain (sqrt) (Right (-1)) |
| 245 | +Left ('sqrt undefined for -1') |
| 246 | + |
| 247 | +> S.chain (sqrt) (Right (25)) |
| 248 | +Right (5) |
| 249 | +``` |
| 250 | + |
| 251 | +#### <a name="Either.prototype.fantasy-land/alt" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L434">`Either#fantasy-land/alt :: Either a b ~> Either a b -> Either a b`</a> |
| 252 | + |
| 253 | + - `alt (Left (x)) (Left (y))` is equivalent to `Left (y)` |
| 254 | + - `alt (Left (x)) (Right (y))` is equivalent to `Right (y)` |
| 255 | + - `alt (Right (x)) (Left (y))` is equivalent to `Right (x)` |
| 256 | + - `alt (Right (x)) (Right (y))` is equivalent to `Right (x)` |
| 257 | + |
| 258 | +```javascript |
| 259 | +> S.alt (Left ('A')) (Left ('B')) |
| 260 | +Left ('B') |
| 261 | + |
| 262 | +> S.alt (Left ('C')) (Right (1)) |
| 263 | +Right (1) |
| 264 | + |
| 265 | +> S.alt (Right (2)) (Left ('D')) |
| 266 | +Right (2) |
| 267 | + |
| 268 | +> S.alt (Right (3)) (Right (4)) |
| 269 | +Right (3) |
| 270 | +``` |
| 271 | + |
| 272 | +#### <a name="Either.prototype.fantasy-land/reduce" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L461">`Either#fantasy-land/reduce :: Either a b ~> ((c, b) -> c, c) -> c`</a> |
| 273 | + |
| 274 | + - `reduce (f) (x) (Left (y))` is equivalent to `x` |
| 275 | + - `reduce (f) (x) (Right (y))` is equivalent to `f (x) (y)` |
| 276 | + |
| 277 | +```javascript |
| 278 | +> S.reduce (S.concat) ([1]) (Left ('sqrt undefined for -1')) |
| 279 | +[1] |
| 280 | + |
| 281 | +> S.reduce (S.concat) ([1]) (Right ([2])) |
| 282 | +[1, 2] |
| 283 | +``` |
| 284 | + |
| 285 | +#### <a name="Either.prototype.fantasy-land/traverse" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L480">`Either#fantasy-land/traverse :: Applicative f => Either a b ~> (TypeRep f, b -> f c) -> f (Either a c)`</a> |
| 286 | + |
| 287 | + - `traverse (A) (f) (Left (x))` is equivalent to `of (A) (Left (x))` |
| 288 | + - `traverse (A) (f) (Right (x))` is equivalent to `map (Right) (f (x))` |
| 289 | + |
| 290 | +```javascript |
| 291 | +> S.traverse (Array) (S.words) (Left ('sqrt undefined for -1')) |
| 292 | +[Left ('sqrt undefined for -1')] |
| 293 | + |
| 294 | +> S.traverse (Array) (S.words) (Right ('foo bar baz')) |
| 295 | +[Right ('foo'), Right ('bar'), Right ('baz')] |
| 296 | +``` |
| 297 | + |
| 298 | +#### <a name="Either.prototype.fantasy-land/extend" href="https://github.com/sanctuary-js/sanctuary-either/blob/v1.0.0/index.js#L499">`Either#fantasy-land/extend :: Either a b ~> (Either a b -> c) -> Either a c`</a> |
| 299 | + |
| 300 | + - `extend (f) (Left (x))` is equivalent to `Left (x)` |
| 301 | + - `extend (f) (Right (x))` is equivalent to `Right (f (Right (x)))` |
| 302 | + |
| 303 | +```javascript |
| 304 | +> S.extend (S.reduce (S.add) (1)) (Left ('sqrt undefined for -1')) |
| 305 | +Left ('sqrt undefined for -1') |
| 306 | + |
| 307 | +> S.extend (S.reduce (S.add) (1)) (Right (99)) |
| 308 | +Right (100) |
| 309 | +``` |
| 310 | + |
| 311 | +[Fantasy Land]: https://github.com/fantasyland/fantasy-land/tree/v3.5.0 |
| 312 | +[`Z.equals`]: https://github.com/sanctuary-js/sanctuary-type-classes/tree/v9.0.0#equals |
| 313 | +[`Z.lte`]: https://github.com/sanctuary-js/sanctuary-type-classes/tree/v9.0.0#lte |
| 314 | +[iff]: https://en.wikipedia.org/wiki/If_and_only_if |
| 315 | +[type identifier]: https://github.com/sanctuary-js/sanctuary-type-identifiers/tree/v2.0.1 |
| 316 | +[type representative]: https://github.com/fantasyland/fantasy-land/tree/v3.5.0#type-representatives |
0 commit comments