Repository: sanctuary-js/sanctuary
Pull request #683 (2020-07-26 03:37:30)

fromLeft and fromRight
Forgot why I never opened this, but I can't see a reason to not push it forward. Let me know if there is anything you'd like me to add / change etc.

Summary of changes: Add functionality of `fromLeft` and `fromRight`

`fromLeft :: a -> Either a b -> a`
`fromRight :: b -> Either a b -> b`


davidchambers: This pull request contains a subset of the changes proposed in #644. This pull request does not change the behaviour of `fromEither`, meaning that these changes could be included in the next minor release. This would result in two equivalent functions coexisting, which would be unusual given our avoidance of aliases. It seems like a reasonable course of action.

davidchambers: @ryanbas21, as you may or may not be aware, #644 was open at the time you made your additions. That pull request has already been reviewed and discussed, and includes documentation. It makes sense to reuse @futpib's work rather than reproduce it, so I cherry-picked one of the commits and reverted the changes to `fromEither` included in that commit.

@futpib, I hope you are comfortable with me modifying one of your commits.

@ryanbas21, I hope you are comfortable with me commandeering your pull request.


Patch:
diff --git a/index.js b/index.js
index b9fa21f..f0f62a5 100644
--- a/index.js
+++ b/index.js
@@ -2079,7 +2079,7 @@
   //. a Just, the return value is the result of applying the function to
   //. the Just's value. Otherwise, the first argument is returned.
   //.
-  //. See also [`maybe_`](#maybe_).
+  //. See also [`maybe_`](#maybe_) and [`fromMaybe`](#fromMaybe).
   //.
   //. ```javascript
   //. > S.maybe (0) (S.prop ('length')) (S.Just ('refuge'))
@@ -2133,7 +2133,7 @@
   //. Takes a default value and a Maybe, and returns the Maybe's value
   //. if the Maybe is a Just; the default value otherwise.
   //.
-  //. See also [`fromMaybe_`](#fromMaybe_) and
+  //. See also [`maybe`](#maybe), [`fromMaybe_`](#fromMaybe_), and
   //. [`maybeToNullable`](#maybeToNullable).
   //.
   //. ```javascript
@@ -2342,6 +2342,8 @@
   //. is a Left, or the result of applying the second function to the
   //. Right's value, if the Either is a Right.
   //.
+  //. See also [`fromLeft`](#fromLeft) and [`fromRight`](#fromRight).
+  //.
   //. ```javascript
   //. > S.either (S.toUpper) (S.show) (S.Left ('Cannot divide by zero'))
   //. 'CANNOT DIVIDE BY ZERO'
@@ -2362,11 +2364,60 @@
     impl: either
   };
 
+  //# fromLeft :: a -> Either a b -> a
+  //.
+  //. Takes a default value and an Either, and returns the Left value
+  //. if the Either is a Left; the default value otherwise.
+  //.
+  //. See also [`either`](#either) and [`fromRight`](#fromRight).
+  //.
+  //. ```javascript
+  //. > S.fromLeft ('abc') (S.Left ('xyz'))
+  //. 'xyz'
+  //.
+  //. > S.fromLeft ('abc') (S.Right (123))
+  //. 'abc'
+  //. ```
+  function fromLeft(x) {
+    return either (I) (K (x));
+  }
+  _.fromLeft = {
+    consts: {},
+    types: [a, $.Either (a) (b), a],
+    impl: fromLeft
+  };
+
+  //# fromRight :: b -> Either a b -> b
+  //.
+  //. Takes a default value and an Either, and returns the Right value
+  //. if the Either is a Right; the default value otherwise.
+  //.
+  //. See also [`either`](#either) and [`fromLeft`](#fromLeft).
+  //.
+  //. ```javascript
+  //. > S.fromRight (123) (S.Right (789))
+  //. 789
+  //.
+  //. > S.fromRight (123) (S.Left ('abc'))
+  //. 123
+  //. ```
+  function fromRight(x) {
+    return either (K (x)) (I);
+  }
+  _.fromRight = {
+    consts: {},
+    types: [b, $.Either (a) (b), b],
+    impl: fromRight
+  };
+
   //# fromEither :: b -> Either a b -> b
   //.
   //. Takes a default value and an Either, and returns the Right value
   //. if the Either is a Right; the default value otherwise.
   //.
+  //. The behaviour of `fromEither` is likely to change in a future release.
+  //. Please use [`fromRight`](#fromRight) instead.
+  //.
   //. ```javascript
   //. > S.fromEither (0) (S.Right (42))
   //. 42


Test patch:
diff --git a/test/fromLeft.js b/test/fromLeft.js
new file mode 100644
index 0000000..eab9f80
--- /dev/null
+++ b/test/fromLeft.js
@@ -0,0 +1,15 @@
+'use strict';
+
+const S = require ('..');
+
+const eq = require ('./internal/eq');
+
+
+test ('fromLeft', () => {
+
+  eq (S.show (S.fromLeft)) ('fromLeft :: a -> Either a b -> a');
+
+  eq (S.fromLeft ('abc') (S.Left ('xyz'))) ('xyz');
+  eq (S.fromLeft ('abc') (S.Right (123))) ('abc');
+
+});
diff --git a/test/fromRight.js b/test/fromRight.js
new file mode 100644
index 0000000..ac554ee
--- /dev/null
+++ b/test/fromRight.js
@@ -0,0 +1,15 @@
+'use strict';
+
+const S = require ('..');
+
+const eq = require ('./internal/eq');
+
+
+test ('fromRight', () => {
+
+  eq (S.show (S.fromRight)) ('fromRight :: b -> Either a b -> b');
+
+  eq (S.fromRight (123) (S.Right (789))) (789);
+  eq (S.fromRight (123) (S.Left ('abc'))) (123);
+
+});