Repository: sanctuary-js/sanctuary
Pull request #225 (2016-05-30 07:09:52)

maybe: change type of S.Nothing from ‘-> Maybe a’ to ‘Maybe a’
Initially, `S.Nothing` existed both to create the `Nothing` value and to support `R.is(S.Nothing)`. `S.Nothing` is no longer a constructor function, and we now have [`S.isNothing`][1] to answer the question of whether a given value of type `Maybe a` is `Nothing`. This means `S.Nothing` can now be the `Nothing` value, improving Haskell correspondence:

|                   | Nothing           | Just              |
| ----------------- | ----------------- | ----------------- |
| Sanctuary, before | `S.Nothing()`     | `S.Just(42)`      |
| Sanctuary, after  | `S.Nothing`       | `S.Just(42)`      |
| Haskell           | `Nothing`         | `Just 42`         |

Can anyone think of a problem with this change?

---

_This evening I realized for the first time that “nothing” is comprised of “no” and “thing”. I now think Haskell should have gone with `data Maybe a = Thing a | Nothing`. ;)_


[1]: http://sanctuary.js.org/#isNothing


svozza: LGTM.

Patch:
diff --git a/index.js b/index.js
index 05a5fef..b3cb655 100644
--- a/index.js
+++ b/index.js
@@ -46,8 +46,8 @@
 //.
 //. Sanctuary embraces types. JavaScript doesn't support algebraic data types,
 //. but these can be simulated by providing a group of data constructors which
-//. return values with the same set of methods. A value of the Maybe type, for
-//. example, is created via the Nothing constructor or the Just constructor.
+//. return values with the same set of methods. A value of the Either type, for
+//. example, is created via the Left constructor or the Right constructor.
 //.
 //. It's necessary to extend Haskell's notation to describe implicit arguments
 //. to the *methods* provided by Sanctuary's types. In `x.map(y)`, for example,
@@ -650,8 +650,8 @@
   //. > S.lift(S.inc, S.Just(2))
   //. Just(3)
   //.
-  //. > S.lift(S.inc, S.Nothing())
-  //. Nothing()
+  //. > S.lift(S.inc, S.Nothing)
+  //. Nothing
   //. ```
   S.lift =
   def('lift',
@@ -668,8 +668,8 @@
   //. > S.lift2(S.add, S.Just(2), S.Just(3))
   //. Just(5)
   //.
-  //. > S.lift2(S.add, S.Just(2), S.Nothing())
-  //. Nothing()
+  //. > S.lift2(S.add, S.Just(2), S.Nothing)
+  //. Nothing
   //.
   //. > S.lift2(S.and, S.Just(true), S.Just(true))
   //. Just(true)
@@ -692,8 +692,8 @@
   //. > S.lift3(S.reduce, S.Just(S.add), S.Just(0), S.Just([1, 2, 3]))
   //. Just(6)
   //.
-  //. > S.lift3(S.reduce, S.Just(S.add), S.Just(0), S.Nothing())
-  //. Nothing()
+  //. > S.lift3(S.reduce, S.Just(S.add), S.Just(0), S.Nothing)
+  //. Nothing
   //. ```
   S.lift3 =
   def('lift3',
@@ -789,7 +789,7 @@
   //. ### Maybe type
   //.
   //. The Maybe type represents optional values: a value of type `Maybe a` is
-  //. either a Just whose value is of type `a` or a Nothing (with no value).
+  //. either a Just whose value is of type `a` or Nothing (with no value).
   //.
   //. The Maybe type satisfies the [Monoid][], [Monad][], [Traversable][],
   //. and [Extend][] specifications.
@@ -801,25 +801,27 @@
   //# Maybe :: TypeRep Maybe
   //.
   //. The [type representative](#type-representatives) for the Maybe type.
-  var Maybe = S.Maybe = function Maybe() {
-    if (arguments[0] !== sentinel) {
-      throw new Error('Cannot instantiate Maybe');
-    }
+  var Maybe = S.Maybe = function Maybe(x, box) {
+    if (x !== sentinel) throw new Error('Cannot instantiate Maybe');
+    var isJust = box.length > 0;
+    if (isJust) this.value = box[0];
+    this.isNothing = !isJust;
+    this.isJust = isJust;
   };
 
   //# Maybe.empty :: -> Maybe a
   //.
-  //. Returns a Nothing.
+  //. Returns Nothing.
   //.
   //. ```javascript
   //. > S.Maybe.empty()
-  //. Nothing()
+  //. Nothing
   //. ```
   Maybe.empty =
   def('Maybe.empty',
       {},
       [$Maybe(a)],
-      function() { return Nothing(); });
+      function() { return Nothing; });
 
   //# Maybe.of :: a -> Maybe a
   //.
@@ -842,10 +844,10 @@
 
   //# Maybe#isNothing :: Boolean
   //.
-  //. `true` if `this` is a Nothing; `false` if `this` is a Just.
+  //. `true` if `this` is Nothing; `false` if `this` is a Just.
   //.
   //. ```javascript
-  //. > S.Nothing().isNothing
+  //. > S.Nothing.isNothing
   //. true
   //.
   //. > S.Just(42).isNothing
@@ -854,29 +856,29 @@
 
   //# Maybe#isJust :: Boolean
   //.
-  //. `true` if `this` is a Just; `false` if `this` is a Nothing.
+  //. `true` if `this` is a Just; `false` if `this` is Nothing.
   //.
   //. ```javascript
   //. > S.Just(42).isJust
   //. true
   //.
-  //. > S.Nothing().isJust
+  //. > S.Nothing.isJust
   //. false
   //. ```
 
   //# Maybe#ap :: Maybe (a -> b) ~> Maybe a -> Maybe b
   //.
-  //. Takes a value of type `Maybe a` and returns a Nothing unless `this`
+  //. Takes a value of type `Maybe a` and returns Nothing unless `this`
   //. is a Just *and* the argument is a Just, in which case it returns a
   //. Just whose value is the result of of applying this Just's value to
   //. the given Just's value.
   //.
   //. ```javascript
-  //. > S.Nothing().ap(S.Just(42))
-  //. Nothing()
+  //. > S.Nothing.ap(S.Just(42))
+  //. Nothing
   //.
-  //. > S.Just(S.inc).ap(S.Nothing())
-  //. Nothing()
+  //. > S.Just(S.inc).ap(S.Nothing)
+  //. Nothing
   //.
   //. > S.Just(S.inc).ap(S.Just(42))
   //. Just(43)
@@ -889,15 +891,15 @@
 
   //# Maybe#chain :: Maybe a ~> (a -> Maybe b) -> Maybe b
   //.
-  //. Takes a function and returns `this` if `this` is a Nothing; otherwise
+  //. Takes a function and returns `this` if `this` is Nothing; otherwise
   //. it returns the result of applying the function to this Just's value.
   //.
   //. ```javascript
-  //. > S.Nothing().chain(S.parseFloat)
-  //. Nothing()
+  //. > S.Nothing.chain(S.parseFloat)
+  //. Nothing
   //.
   //. > S.Just('xxx').chain(S.parseFloat)
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.Just('12.34').chain(S.parseFloat)
   //. Just(12.34)
@@ -914,8 +916,8 @@
   //. `a` must have a [Semigroup][] (indicated by the presence of a `concat`
   //. method).
   //.
-  //. If `this` is a Nothing and the argument is a Nothing, this method returns
-  //. a Nothing.
+  //. If `this` is Nothing and the argument is Nothing, this method returns
+  //. Nothing.
   //.
   //. If `this` is a Just and the argument is a Just, this method returns a
   //. Just whose value is the result of concatenating this Just's value and
@@ -924,16 +926,16 @@
   //. Otherwise, this method returns the Just.
   //.
   //. ```javascript
-  //. > S.Nothing().concat(S.Nothing())
-  //. Nothing()
+  //. > S.Nothing.concat(S.Nothing)
+  //. Nothing
   //.
   //. > S.Just([1, 2, 3]).concat(S.Just([4, 5, 6]))
   //. Just([1, 2, 3, 4, 5, 6])
   //.
-  //. > S.Nothing().concat(S.Just([1, 2, 3]))
+  //. > S.Nothing.concat(S.Just([1, 2, 3]))
   //. Just([1, 2, 3])
   //.
-  //. > S.Just([1, 2, 3]).concat(S.Nothing())
+  //. > S.Just([1, 2, 3]).concat(S.Nothing)
   //. Just([1, 2, 3])
   //. ```
   Maybe.prototype.concat =
@@ -947,11 +949,11 @@
 
   //# Maybe#empty :: Maybe a ~> Maybe a
   //.
-  //. Returns a Nothing.
+  //. Returns Nothing.
   //.
   //. ```javascript
   //. > S.Just(42).empty()
-  //. Nothing()
+  //. Nothing
   //. ```
   Maybe.prototype.empty =
   def('Maybe#empty',
@@ -963,16 +965,16 @@
   //.
   //. Takes a value of any type and returns `true` if:
   //.
-  //.   - it is a Nothing and `this` is a Nothing; or
+  //.   - it is Nothing and `this` is Nothing; or
   //.
   //.   - it is a Just and `this` is a Just, and their values are equal
   //.     according to [`R.equals`][R.equals].
   //.
   //. ```javascript
-  //. > S.Nothing().equals(S.Nothing())
+  //. > S.Nothing.equals(S.Nothing)
   //. true
   //.
-  //. > S.Nothing().equals(null)
+  //. > S.Nothing.equals(null)
   //. false
   //.
   //. > S.Just([1, 2, 3]).equals(S.Just([1, 2, 3]))
@@ -981,7 +983,7 @@
   //. > S.Just([1, 2, 3]).equals(S.Just([3, 2, 1]))
   //. false
   //.
-  //. > S.Just([1, 2, 3]).equals(S.Nothing())
+  //. > S.Just([1, 2, 3]).equals(S.Nothing)
   //. false
   //. ```
   Maybe.prototype.equals =
@@ -996,13 +998,13 @@
 
   //# Maybe#extend :: Maybe a ~> (Maybe a -> a) -> Maybe a
   //.
-  //. Takes a function and returns `this` if `this` is a Nothing; otherwise
-  //. it returns a Just whose value is the result of applying the function to
-  //. `this`.
+  //. Takes a function and returns `this` if `this` is Nothing; otherwise
+  //. it returns a Just whose value is the result of applying the function
+  //. to `this`.
   //.
   //. ```javascript
-  //. > S.Nothing().extend(x => x.value + 1)
-  //. Nothing()
+  //. > S.Nothing.extend(x => x.value + 1)
+  //. Nothing
   //.
   //. > S.Just(42).extend(x => x.value + 1)
   //. Just(43)
@@ -1023,7 +1025,7 @@
   //. Just(42)
   //.
   //. > S.Just(43).filter(n => n % 2 === 0)
-  //. Nothing()
+  //. Nothing
   //. ```
   Maybe.prototype.filter =
   method('Maybe#filter',
@@ -1033,13 +1035,13 @@
 
   //# Maybe#map :: Maybe a ~> (a -> b) -> Maybe b
   //.
-  //. Takes a function and returns `this` if `this` is a Nothing; otherwise
-  //. it returns a Just whose value is the result of applying the function to
-  //. this Just's value.
+  //. Takes a function and returns `this` if `this` is Nothing; otherwise
+  //. it returns a Just whose value is the result of applying the function
+  //. to this Just's value.
   //.
   //. ```javascript
-  //. > S.Nothing().map(S.inc)
-  //. Nothing()
+  //. > S.Nothing.map(S.inc)
+  //. Nothing
   //.
   //. > S.Just([1, 2, 3]).map(S.sum)
   //. Just(6)
@@ -1057,7 +1059,7 @@
   //. Takes a value of any type and returns a Just with the given value.
   //.
   //. ```javascript
-  //. > S.Nothing().of(42)
+  //. > S.Nothing.of(42)
   //. Just(42)
   //. ```
   Maybe.prototype.of =
@@ -1070,13 +1072,13 @@
   //.
   //. Takes a function and an initial value of any type, and returns:
   //.
-  //.   - the initial value if `this` is a Nothing; otherwise
+  //.   - the initial value if `this` is Nothing; otherwise
   //.
   //.   - the result of applying the function to the initial value and this
   //.     Just's value.
   //.
   //. ```javascript
-  //. > S.Nothing().reduce(S.add, 10)
+  //. > S.Nothing.reduce(S.add, 10)
   //. 10
   //.
   //. > S.Just(5).reduce(S.add, 10)
@@ -1094,13 +1096,13 @@
   //.
   //. Evaluates an applicative action contained within the Maybe, resulting in:
   //.
-  //.   - a pure applicative of a Nothing if `this` is a Nothing; otherwise
+  //.   - a pure applicative of Nothing if `this` is Nothing; otherwise
   //.
   //.   - an applicative of Just the value of the evaluated action.
   //.
   //. ```javascript
-  //. > S.Nothing().sequence(S.Either.of)
-  //. Right(Nothing())
+  //. > S.Nothing.sequence(S.Either.of)
+  //. Right(Nothing)
   //.
   //. > S.Just(S.Right(42)).sequence(S.Either.of)
   //. Right(Just(42))
@@ -1118,10 +1120,10 @@
 
   //# Maybe#toBoolean :: Maybe a ~> Boolean
   //.
-  //. Returns `false` if `this` is a Nothing; `true` if `this` is a Just.
+  //. Returns `false` if `this` is Nothing; `true` if `this` is a Just.
   //.
   //. ```javascript
-  //. > S.Nothing().toBoolean()
+  //. > S.Nothing.toBoolean()
   //. false
   //.
   //. > S.Just(42).toBoolean()
@@ -1138,8 +1140,8 @@
   //. Returns the string representation of the Maybe.
   //.
   //. ```javascript
-  //. > S.Nothing().toString()
-  //. 'Nothing()'
+  //. > S.Nothing.toString()
+  //. 'Nothing'
   //.
   //. > S.Just([1, 2, 3]).toString()
   //. 'Just([1, 2, 3])'
@@ -1150,7 +1152,7 @@
          [$Maybe(a), $.String],
          function(maybe) {
            return maybe.isJust ? 'Just(' + R.toString(maybe.value) + ')'
-                               : 'Nothing()';
+                               : 'Nothing';
          });
 
   //# Maybe#inspect :: Maybe a ~> String
@@ -1161,28 +1163,23 @@
   //. See also [`Maybe#toString`](#Maybe.prototype.toString).
   //.
   //. ```javascript
-  //. > S.Nothing().inspect()
-  //. 'Nothing()'
+  //. > S.Nothing.inspect()
+  //. 'Nothing'
   //.
   //. > S.Just([1, 2, 3]).inspect()
   //. 'Just([1, 2, 3])'
   //. ```
   Maybe.prototype.inspect = inspect;
 
-  //# Nothing :: -> Maybe a
+  //# Nothing :: Maybe a
   //.
-  //. Returns a Nothing.
+  //. Nothing.
   //.
   //. ```javascript
-  //. > S.Nothing()
-  //. Nothing()
+  //. > S.Nothing
+  //. Nothing
   //. ```
-  var Nothing = S.Nothing = function() {
-    var nothing = new Maybe(sentinel);
-    nothing.isNothing = true;
-    nothing.isJust = false;
-    return nothing;
-  };
+  var Nothing = S.Nothing = new Maybe(sentinel, []);
 
   //# Just :: a -> Maybe a
   //.
@@ -1192,20 +1189,14 @@
   //. > S.Just(42)
   //. Just(42)
   //. ```
-  var Just = S.Just = function(value) {
-    var just = new Maybe(sentinel);
-    just.isNothing = false;
-    just.isJust = true;
-    just.value = value;
-    return just;
-  };
+  var Just = S.Just = function(value) { return new Maybe(sentinel, [value]); };
 
   //# isNothing :: Maybe a -> Boolean
   //.
-  //. Returns `true` if the given Maybe is a Nothing; `false` if it is a Just.
+  //. Returns `true` if the given Maybe is Nothing; `false` if it is a Just.
   //.
   //. ```javascript
-  //. > S.isNothing(S.Nothing())
+  //. > S.isNothing(S.Nothing)
   //. true
   //.
   //. > S.isNothing(S.Just(42))
@@ -1219,13 +1210,13 @@
 
   //# isJust :: Maybe a -> Boolean
   //.
-  //. Returns `true` if the given Maybe is a Just; `false` if it is a Nothing.
+  //. Returns `true` if the given Maybe is a Just; `false` if it is Nothing.
   //.
   //. ```javascript
   //. > S.isJust(S.Just(42))
   //. true
   //.
-  //. > S.isJust(S.Nothing())
+  //. > S.isJust(S.Nothing)
   //. false
   //. ```
   S.isJust =
@@ -1245,7 +1236,7 @@
   //. > S.fromMaybe(0, S.Just(42))
   //. 42
   //.
-  //. > S.fromMaybe(0, S.Nothing())
+  //. > S.fromMaybe(0, S.Nothing)
   //. 0
   //. ```
   var fromMaybe = S.fromMaybe =
@@ -1265,7 +1256,7 @@
   //. > S.maybeToNullable(S.Just(42))
   //. 42
   //.
-  //. > S.maybeToNullable(S.Nothing())
+  //. > S.maybeToNullable(S.Nothing)
   //. null
   //. ```
   S.maybeToNullable =
@@ -1281,7 +1272,7 @@
   //.
   //. ```javascript
   //. > S.toMaybe(null)
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.toMaybe(42)
   //. Just(42)
@@ -1290,7 +1281,7 @@
   def('toMaybe',
       {},
       [a, $Maybe(a)],
-      function(x) { return x == null ? Nothing() : Just(x); });
+      function(x) { return x == null ? Nothing : Just(x); });
 
   //# maybe :: b -> (a -> b) -> Maybe a -> b
   //.
@@ -1302,7 +1293,7 @@
   //. > S.maybe(0, R.length, S.Just('refuge'))
   //. 6
   //.
-  //. > S.maybe(0, R.length, S.Nothing())
+  //. > S.maybe(0, R.length, S.Nothing)
   //. 0
   //. ```
   var maybe = S.maybe =
@@ -1319,7 +1310,7 @@
   //. See also [`lefts`](#lefts) and [`rights`](#rights).
   //.
   //. ```javascript
-  //. > S.justs([S.Just('foo'), S.Nothing(), S.Just('baz')])
+  //. > S.justs([S.Just('foo'), S.Nothing, S.Just('baz')])
   //. ['foo', 'baz']
   //. ```
   var justs = S.justs =
@@ -1332,7 +1323,7 @@
   //.
   //. Takes a function and an array, applies the function to each element of
   //. the array, and returns an array of "successful" results. If the result of
-  //. applying the function to an element of the array is a Nothing, the result
+  //. applying the function to an element of the array is Nothing, the result
   //. is discarded; if the result is a Just, the Just's value is included in
   //. the output array.
   //.
@@ -1352,7 +1343,7 @@
   //.
   //. Takes a unary function `f` which may throw and a value `x` of any type,
   //. and applies `f` to `x` inside a `try` block. If an exception is caught,
-  //. the return value is a Nothing; otherwise the return value is Just the
+  //. the return value is Nothing; otherwise the return value is Just the
   //. result of applying `f` to `x`.
   //.
   //. See also [`encaseEither`](#encaseEither).
@@ -1362,7 +1353,7 @@
   //. Just(2)
   //.
   //. > S.encase(eval, '1 +')
-  //. Nothing()
+  //. Nothing
   //. ```
   var encase = S.encase =
   def('encase',
@@ -1372,7 +1363,7 @@
         try {
           return Just(f(x));
         } catch (err) {
-          return Nothing();
+          return Nothing;
         }
       });
 
@@ -1389,7 +1380,7 @@
         try {
           return Just(f(x)(y));
         } catch (err) {
-          return Nothing();
+          return Nothing;
         }
       });
 
@@ -1422,7 +1413,7 @@
         try {
           return Just(f(x)(y)(z));
         } catch (err) {
-          return Nothing();
+          return Nothing;
         }
       });
 
@@ -1446,7 +1437,7 @@
 
   //# maybeToEither :: a -> Maybe b -> Either a b
   //.
-  //. Converts a Maybe to an Either. A Nothing becomes a Left (containing the
+  //. Converts a Maybe to an Either. Nothing becomes a Left (containing the
   //. first argument); a Just becomes a Right.
   //.
   //. See also [`eitherToMaybe`](#eitherToMaybe).
@@ -1746,8 +1737,8 @@
   //. > S.Right(S.Just(42)).sequence(S.Maybe.of)
   //. Just(Right(42))
   //.
-  //. > S.Right(S.Nothing()).sequence(S.Maybe.of)
-  //. Nothing()
+  //. > S.Right(S.Nothing).sequence(S.Maybe.of)
+  //. Nothing
   //. ```
   Either.prototype.sequence =
   method('Either#sequence',
@@ -2058,14 +2049,14 @@
 
   //# eitherToMaybe :: Either a b -> Maybe b
   //.
-  //. Converts an Either to a Maybe. A Left becomes a Nothing; a Right becomes
+  //. Converts an Either to a Maybe. A Left becomes Nothing; a Right becomes
   //. a Just.
   //.
   //. See also [`maybeToEither`](#maybeToEither).
   //.
   //. ```javascript
   //. > S.eitherToMaybe(S.Left('Cannot divide by zero'))
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.eitherToMaybe(S.Right(42))
   //. Just(42)
@@ -2075,7 +2066,7 @@
       {},
       [$Either(a, b), $Maybe(b)],
       function(either) {
-        return either.isLeft ? Nothing() : Just(either.value);
+        return either.isLeft ? Nothing : Just(either.value);
       });
 
   //. ### Alternative
@@ -2119,8 +2110,8 @@
   //. > S.and(S.Just(1), S.Just(2))
   //. Just(2)
   //.
-  //. > S.and(S.Nothing(), S.Just(3))
-  //. Nothing()
+  //. > S.and(S.Nothing, S.Just(3))
+  //. Nothing
   //. ```
   S.and =
   def('and',
@@ -2139,7 +2130,7 @@
   //. > S.or(S.Just(1), S.Just(2))
   //. Just(1)
   //.
-  //. > S.or(S.Nothing(), S.Just(3))
+  //. > S.or(S.Nothing, S.Just(3))
   //. Just(3)
   //. ```
   var or = S.or =
@@ -2158,11 +2149,11 @@
   //. `empty` methods.
   //.
   //. ```javascript
-  //. > S.xor(S.Nothing(), S.Just(1))
+  //. > S.xor(S.Nothing, S.Just(1))
   //. Just(1)
   //.
   //. > S.xor(S.Just(2), S.Just(3))
-  //. Nothing()
+  //. Nothing
   //. ```
   S.xor =
   def('xor',
@@ -2315,7 +2306,7 @@
   //. Just(['c', 'd', 'e'])
   //.
   //. > S.slice(1, 6, ['a', 'b', 'c', 'd', 'e'])
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.slice(2, 6, 'banana')
   //. Just('nana')
@@ -2331,7 +2322,7 @@
 
         return Math.abs(start) <= len && Math.abs(end) <= len && A <= Z ?
           Just(R.slice(A, Z, xs)) :
-          Nothing();
+          Nothing;
       });
 
   //# at :: Integer -> [a] -> Maybe a
@@ -2345,7 +2336,7 @@
   //. Just('c')
   //.
   //. > S.at(5, ['a', 'b', 'c', 'd', 'e'])
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.at(-2, ['a', 'b', 'c', 'd', 'e'])
   //. Just('d')
@@ -2368,7 +2359,7 @@
   //. Just(1)
   //.
   //. > S.head([])
-  //. Nothing()
+  //. Nothing
   //. ```
   S.head =
   def('head',
@@ -2386,7 +2377,7 @@
   //. Just(3)
   //.
   //. > S.last([])
-  //. Nothing()
+  //. Nothing
   //. ```
   S.last =
   def('last',
@@ -2405,7 +2396,7 @@
   //. Just([2, 3])
   //.
   //. > S.tail([])
-  //. Nothing()
+  //. Nothing
   //. ```
   S.tail =
   def('tail',
@@ -2424,7 +2415,7 @@
   //. Just([1, 2])
   //.
   //. > S.init([])
-  //. Nothing()
+  //. Nothing
   //. ```
   S.init =
   def('init',
@@ -2447,14 +2438,14 @@
   //. Just('abcd')
   //.
   //. > S.take(4, ['a', 'b', 'c'])
-  //. Nothing()
+  //. Nothing
   //. ```
   S.take =
   def('take',
       {},
       [$.Integer, List(a), $Maybe(List(a))],
       function(n, xs) {
-        return n < 0 || negativeZero(n) ? Nothing() : slice(0, n, xs);
+        return n < 0 || negativeZero(n) ? Nothing : slice(0, n, xs);
       });
 
   //# takeLast :: Integer -> [a] -> Maybe [a]
@@ -2472,14 +2463,14 @@
   //. Just('defg')
   //.
   //. > S.takeLast(4, ['a', 'b', 'c'])
-  //. Nothing()
+  //. Nothing
   //. ```
   S.takeLast =
   def('takeLast',
       {},
       [$.Integer, List(a), $Maybe(List(a))],
       function(n, xs) {
-        return n < 0 || negativeZero(n) ? Nothing() : slice(-n, -0, xs);
+        return n < 0 || negativeZero(n) ? Nothing : slice(-n, -0, xs);
       });
 
   //# drop :: Integer -> [a] -> Maybe [a]
@@ -2497,14 +2488,14 @@
   //. Just('efg')
   //.
   //. > S.drop(4, 'abc')
-  //. Nothing()
+  //. Nothing
   //. ```
   S.drop =
   def('drop',
       {},
       [$.Integer, List(a), $Maybe(List(a))],
       function(n, xs) {
-        return n < 0 || negativeZero(n) ? Nothing() : slice(n, -0, xs);
+        return n < 0 || negativeZero(n) ? Nothing : slice(n, -0, xs);
       });
 
   //# dropLast :: Integer -> [a] -> Maybe [a]
@@ -2522,14 +2513,14 @@
   //. Just('abc')
   //.
   //. > S.dropLast(4, 'abc')
-  //. Nothing()
+  //. Nothing
   //. ```
   S.dropLast =
   def('dropLast',
       {},
       [$.Integer, List(a), $Maybe(List(a))],
       function(n, xs) {
-        return n < 0 || negativeZero(n) ? Nothing() : slice(0, -n, xs);
+        return n < 0 || negativeZero(n) ? Nothing : slice(0, -n, xs);
       });
 
   //# reverse :: [a] -> [a]
@@ -2587,13 +2578,13 @@
   //. Just(1)
   //.
   //. > S.indexOf('x', ['b', 'a', 'n', 'a', 'n', 'a'])
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.indexOf('an', 'banana')
   //. Just(1)
   //.
   //. > S.indexOf('ax', 'banana')
-  //. Nothing()
+  //. Nothing
   //. ```
   S.indexOf = sanctifyIndexOf('indexOf');
 
@@ -2612,13 +2603,13 @@
   //. Just(5)
   //.
   //. > S.lastIndexOf('x', ['b', 'a', 'n', 'a', 'n', 'a'])
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.lastIndexOf('an', 'banana')
   //. Just(3)
   //.
   //. > S.lastIndexOf('ax', 'banana')
-  //. Nothing()
+  //. Nothing
   //. ```
   S.lastIndexOf = sanctifyIndexOf('lastIndexOf');
 
@@ -2669,7 +2660,7 @@
   //. Just(-2)
   //.
   //. > S.find(n => n < 0, [1, 2, 3, 4, 5])
-  //. Nothing()
+  //. Nothing
   //. ```
   S.find =
   def('find',
@@ -2681,7 +2672,7 @@
             return Just(xs[idx]);
           }
         }
-        return Nothing();
+        return Nothing;
       });
 
   //# pluck :: Accessible a => TypeRep b -> String -> Array a -> Array (Maybe b)
@@ -2696,7 +2687,7 @@
   //.
   //. ```javascript
   //. > S.pluck(Number, 'x', [{x: 1}, {x: 2}, {x: '3'}, {x: null}, {}])
-  //. [Just(1), Just(2), Nothing(), Nothing(), Nothing()]
+  //. [Just(1), Just(2), Nothing, Nothing, Nothing]
   //. ```
   S.pluck =
   def('pluck',
@@ -2760,13 +2751,13 @@
   //. function is initially applied to the seed value. Each application
   //. of the function should result in either:
   //.
-  //.   - a Nothing, in which case the array is returned; or
+  //.   - Nothing, in which case the array is returned; or
   //.
   //.   - Just a pair, in which case the first element is appended to
   //.     the array and the function is applied to the second element.
   //.
   //. ```javascript
-  //. > S.unfoldr(n => n < 5 ? S.Just([n, n + 1]) : S.Nothing(), 1)
+  //. > S.unfoldr(n => n < 5 ? S.Just([n, n + 1]) : S.Nothing, 1)
   //. [1, 2, 3, 4]
   //. ```
   S.unfoldr =
@@ -2842,10 +2833,10 @@
   //. Just(1)
   //.
   //. > S.get(Number, 'x', {x: '1', y: '2'})
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.get(Number, 'x', {})
-  //. Nothing()
+  //. Nothing
   //. ```
   var get = S.get =
   def('get',
@@ -2867,10 +2858,10 @@
   //. Just(42)
   //.
   //. > S.gets(Number, ['a', 'b', 'c'], {a: {b: {c: '42'}}})
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.gets(Number, ['a', 'b', 'c'], {})
-  //. Nothing()
+  //. Nothing
   //. ```
   S.gets =
   def('gets',
@@ -2879,9 +2870,7 @@
       function(type, keys, obj) {
         var x = obj;
         for (var idx = 0; idx < keys.length; idx += 1) {
-          if (x == null) {
-            return Nothing();
-          }
+          if (x == null) return Nothing;
           x = x[keys[idx]];
         }
         return filter(is(type), Just(x));
@@ -2980,7 +2969,7 @@
   //. > S.sum(S.Just(42))
   //. 42
   //.
-  //. > S.sum(S.Nothing())
+  //. > S.sum(S.Nothing)
   //. 0
   //. ```
   var sum = S.sum =
@@ -3059,7 +3048,7 @@
   //. > S.product(S.Just(42))
   //. 42
   //.
-  //. > S.product(S.Nothing())
+  //. > S.product(S.Nothing)
   //. 1
   //. ```
   S.product =
@@ -3092,13 +3081,13 @@
   //. S.Just(3)
   //.
   //. > S.mean([])
-  //. S.Nothing()
+  //. S.Nothing
   //.
   //. > S.mean(S.Just(42))
   //. S.Just(42)
   //.
-  //. > S.mean(S.Nothing())
-  //. S.Nothing()
+  //. > S.mean(S.Nothing)
+  //. S.Nothing
   //. ```
   S.mean =
   def('mean',
@@ -3114,7 +3103,7 @@
           {total: 0, count: 0},
           foldable
         );
-        return result.count === 0 ? Nothing()
+        return result.count === 0 ? Nothing
                                   : Just(result.total / result.count);
       });
 
@@ -3218,7 +3207,7 @@
   //. Just(new Date('2011-01-19T17:40:00.000Z'))
   //.
   //. > S.parseDate('today')
-  //. Nothing()
+  //. Nothing
   //. ```
   S.parseDate =
   def('parseDate',
@@ -3226,7 +3215,7 @@
       [$.String, $Maybe($.Date)],
       function(s) {
         var d = new Date(s);
-        return d.valueOf() === d.valueOf() ? Just(d) : Nothing();
+        return d.valueOf() === d.valueOf() ? Just(d) : Nothing;
       });
 
   //  requiredNonCapturingGroup :: Array String -> String
@@ -3273,7 +3262,7 @@
   //. Just(-123.45)
   //.
   //. > S.parseFloat('foo.bar')
-  //. Nothing()
+  //. Nothing
   //. ```
   S.parseFloat =
   def('parseFloat',
@@ -3300,7 +3289,7 @@
   //. Just(255)
   //.
   //. > S.parseInt(16, '0xGG')
-  //. Nothing()
+  //. Nothing
   //. ```
   S.parseInt =
   def('parseInt',
@@ -3338,10 +3327,10 @@
   //. Just(['foo', 'bar', 'baz'])
   //.
   //. > S.parseJson(Array, '[')
-  //. Nothing()
+  //. Nothing
   //.
   //. > S.parseJson(Object, '["foo","bar","baz"]')
-  //. Nothing()
+  //. Nothing
   //. ```
   S.parseJson =
   def('parseJson',
@@ -3411,7 +3400,7 @@
   //.
   //. Takes a pattern and a string, and returns Just an array of matches
   //. if the pattern matches the string; Nothing otherwise. Each match has
-  //. type `Maybe String`, where a Nothing represents an unmatched optional
+  //. type `Maybe String`, where Nothing represents an unmatched optional
   //. capturing group.
   //.
   //. ```javascript
@@ -3419,7 +3408,7 @@
   //. Just([Just('goodbye'), Just('good')])
   //.
   //. > S.match(/(good)?bye/, 'bye')
-  //. Just([Just('bye'), Nothing()])
+  //. Just([Just('bye'), Nothing])
   //. ```
   S.match =
   def('match',
@@ -3427,7 +3416,7 @@
       [$.RegExp, $.String, $Maybe($.Array($Maybe($.String)))],
       function(pattern, s) {
         var match = s.match(pattern);
-        return match == null ? Nothing() : Just(R.map(toMaybe, match));
+        return match == null ? Nothing : Just(R.map(toMaybe, match));
       });
 
   //. ### String


Test patch:
diff --git a/test/Maybe/Just.js b/test/Maybe/Just.js
index c229f11..ecafdbb 100644
--- a/test/Maybe/Just.js
+++ b/test/Maybe/Just.js
@@ -23,7 +23,7 @@ describe('Just', function() {
 
   it('provides an "ap" method', function() {
     eq(S.Just(S.inc).ap.length, 1);
-    eq(S.Just(S.inc).ap(S.Nothing()), S.Nothing());
+    eq(S.Just(S.inc).ap(S.Nothing), S.Nothing);
     eq(S.Just(S.inc).ap(S.Just(42)), S.Just(43));
 
     throws(function() { S.Just(S.inc).ap([1, 2, 3]); },
@@ -58,7 +58,7 @@ describe('Just', function() {
 
   it('provides a "concat" method', function() {
     eq(S.Just('foo').concat.length, 1);
-    eq(S.Just('foo').concat(S.Nothing()), S.Just('foo'));
+    eq(S.Just('foo').concat(S.Nothing), S.Just('foo'));
     eq(S.Just('foo').concat(S.Just('bar')), S.Just('foobar'));
 
     throws(function() { S.Just('foo').concat([1, 2, 3]); },
@@ -114,7 +114,7 @@ describe('Just', function() {
     eq(S.Just(42).equals.length, 1);
     eq(S.Just(42).equals(S.Just(42)), true);
     eq(S.Just(42).equals(S.Just(43)), false);
-    eq(S.Just(42).equals(S.Nothing()), false);
+    eq(S.Just(42).equals(S.Nothing), false);
     eq(S.Just(42).equals(null), false);
 
     // Value-based equality:
@@ -153,9 +153,9 @@ describe('Just', function() {
   it('provides a "filter" method', function() {
     eq(S.Just(42).filter.length, 1);
     eq(S.Just(42).filter(R.T), S.Just(42));
-    eq(S.Just(42).filter(R.F), S.Nothing());
+    eq(S.Just(42).filter(R.F), S.Nothing);
     eq(S.Just(42).filter(function(n) { return n > 0; }), S.Just(42));
-    eq(S.Just(42).filter(function(n) { return n < 0; }), S.Nothing());
+    eq(S.Just(42).filter(function(n) { return n < 0; }), S.Nothing);
 
     var m = S.Just(-5);
     var f = function(n) { return n * n; };
diff --git a/test/Maybe/Maybe.js b/test/Maybe/Maybe.js
index 7f82157..ef0bfe2 100644
--- a/test/Maybe/Maybe.js
+++ b/test/Maybe/Maybe.js
@@ -35,7 +35,7 @@ var IdentityArb = function(arb) {
 
 //  MaybeArb :: Arbitrary a -> Arbitrary (Maybe a)
 var MaybeArb = function(arb) {
-  return jsc.oneof(JustArb(arb), jsc.constant(S.Nothing()));
+  return jsc.oneof(JustArb(arb), jsc.constant(S.Nothing));
 };
 
 //  JustArb :: Arbitrary a -> Arbitrary (Maybe a)
diff --git a/test/Maybe/MaybeType.js b/test/Maybe/MaybeType.js
index 3ae0003..61a2514 100644
--- a/test/Maybe/MaybeType.js
+++ b/test/Maybe/MaybeType.js
@@ -9,7 +9,7 @@ var S = require('../..');
 describe('MaybeType', function() {
 
   it('has its type definition exported', function() {
-    eq($.test($.env, S.MaybeType($.Number), S.Nothing()), true);
+    eq($.test($.env, S.MaybeType($.Number), S.Nothing), true);
     eq($.test($.env, S.MaybeType($.Number), S.Just(42)), true);
     eq($.test($.env, S.MaybeType($.Number), S.Just('42')), false);
     eq($.test($.env, S.MaybeType($.Number), S.Right(42)), false);
diff --git a/test/Maybe/Nothing.js b/test/Maybe/Nothing.js
index 9f2e83d..bcc36d8 100644
--- a/test/Maybe/Nothing.js
+++ b/test/Maybe/Nothing.js
@@ -13,20 +13,18 @@ var square = require('../utils').square;
 
 describe('Nothing', function() {
 
-  it('is a data constructor', function() {
-    eq(typeof S.Nothing, 'function');
-    eq(S.Nothing.length, 0);
-    eq(S.Nothing()['@@type'], 'sanctuary/Maybe');
-    eq(S.Nothing().isNothing, true);
-    eq(S.Nothing().isJust, false);
+  it('is a member of the "Maybe a" type', function() {
+    eq(S.Nothing['@@type'], 'sanctuary/Maybe');
+    eq(S.Nothing.isNothing, true);
+    eq(S.Nothing.isJust, false);
   });
 
   it('provides an "ap" method', function() {
-    eq(S.Nothing().ap.length, 1);
-    eq(S.Nothing().ap(S.Nothing()), S.Nothing());
-    eq(S.Nothing().ap(S.Just(42)), S.Nothing());
+    eq(S.Nothing.ap.length, 1);
+    eq(S.Nothing.ap(S.Nothing), S.Nothing);
+    eq(S.Nothing.ap(S.Just(42)), S.Nothing);
 
-    throws(function() { S.Nothing().ap([1, 2, 3]); },
+    throws(function() { S.Nothing.ap([1, 2, 3]); },
            errorEq(TypeError,
                    'Invalid value\n' +
                    '\n' +
@@ -40,10 +38,10 @@ describe('Nothing', function() {
   });
 
   it('provides a "chain" method', function() {
-    eq(S.Nothing().chain.length, 1);
-    eq(S.Nothing().chain(S.head), S.Nothing());
+    eq(S.Nothing.chain.length, 1);
+    eq(S.Nothing.chain(S.head), S.Nothing);
 
-    throws(function() { S.Nothing().chain(null); },
+    throws(function() { S.Nothing.chain(null); },
            errorEq(TypeError,
                    'Invalid value\n' +
                    '\n' +
@@ -57,11 +55,11 @@ describe('Nothing', function() {
   });
 
   it('provides a "concat" method', function() {
-    eq(S.Nothing().concat.length, 1);
-    eq(S.Nothing().concat(S.Nothing()), S.Nothing());
-    eq(S.Nothing().concat(S.Just('foo')), S.Just('foo'));
+    eq(S.Nothing.concat.length, 1);
+    eq(S.Nothing.concat(S.Nothing), S.Nothing);
+    eq(S.Nothing.concat(S.Just('foo')), S.Just('foo'));
 
-    throws(function() { S.Nothing().concat(null); },
+    throws(function() { S.Nothing.concat(null); },
            errorEq(TypeError,
                    'Invalid value\n' +
                    '\n' +
@@ -73,7 +71,7 @@ describe('Nothing', function() {
                    '\n' +
                    'The value at position 1 is not a member of ‘Maybe a’.\n'));
 
-    throws(function() { S.Nothing().concat(S.Just(1)); },
+    throws(function() { S.Nothing.concat(S.Just(1)); },
            errorEq(TypeError,
                    'Type-class constraint violation\n' +
                    '\n' +
@@ -87,24 +85,24 @@ describe('Nothing', function() {
   });
 
   it('provides an "equals" method', function() {
-    eq(S.Nothing().equals.length, 1);
-    eq(S.Nothing().equals(S.Nothing()), true);
-    eq(S.Nothing().equals(S.Just(42)), false);
-    eq(S.Nothing().equals(null), false);
+    eq(S.Nothing.equals.length, 1);
+    eq(S.Nothing.equals(S.Nothing), true);
+    eq(S.Nothing.equals(S.Just(42)), false);
+    eq(S.Nothing.equals(null), false);
   });
 
   it('provides an "extend" method', function() {
-    eq(S.Nothing().extend.length, 1);
-    eq(S.Nothing().extend(function(x) { return x.value / 2; }), S.Nothing());
+    eq(S.Nothing.extend.length, 1);
+    eq(S.Nothing.extend(function(x) { return x.value / 2; }), S.Nothing);
 
     // associativity
-    var w = S.Nothing();
+    var w = S.Nothing;
     var f = function(x) { return x.value + 1; };
     var g = function(x) { return x.value * x.value; };
     eq(w.extend(g).extend(f),
        w.extend(function(_w) { return f(_w.extend(g)); }));
 
-    throws(function() { S.Nothing().extend(null); },
+    throws(function() { S.Nothing.extend(null); },
            errorEq(TypeError,
                    'Invalid value\n' +
                    '\n' +
@@ -118,11 +116,11 @@ describe('Nothing', function() {
   });
 
   it('provides a "filter" method', function() {
-    eq(S.Nothing().filter.length, 1);
-    eq(S.Nothing().filter(R.T), S.Nothing());
-    eq(S.Nothing().filter(R.F), S.Nothing());
+    eq(S.Nothing.filter.length, 1);
+    eq(S.Nothing.filter(R.T), S.Nothing);
+    eq(S.Nothing.filter(R.F), S.Nothing);
 
-    var m = S.Nothing();
+    var m = S.Nothing;
     var f = function(n) { return n * n; };
     var p = function(n) { return n < 0; };
     var q = function(n) { return n > 0; };
@@ -132,7 +130,7 @@ describe('Nothing', function() {
     assert(m.map(f).filter(q)
            .equals(m.filter(function(x) { return q(f(x)); }).map(f)));
 
-    throws(function() { S.Nothing().filter(null); },
+    throws(function() { S.Nothing.filter(null); },
            errorEq(TypeError,
                    'Invalid value\n' +
                    '\n' +
@@ -146,10 +144,10 @@ describe('Nothing', function() {
   });
 
   it('provides a "map" method', function() {
-    eq(S.Nothing().map.length, 1);
-    eq(S.Nothing().map(function() { return 42; }), S.Nothing());
+    eq(S.Nothing.map.length, 1);
+    eq(S.Nothing.map(function() { return 42; }), S.Nothing);
 
-    throws(function() { S.Nothing().map(null); },
+    throws(function() { S.Nothing.map(null); },
            errorEq(TypeError,
                    'Invalid value\n' +
                    '\n' +
@@ -163,10 +161,10 @@ describe('Nothing', function() {
   });
 
   it('provides a "reduce" method', function() {
-    eq(S.Nothing().reduce.length, 2);
-    eq(S.Nothing().reduce(function(a, b) { return a + b; }, 10), 10);
+    eq(S.Nothing.reduce.length, 2);
+    eq(S.Nothing.reduce(function(a, b) { return a + b; }, 10), 10);
 
-    throws(function() { S.Nothing().reduce(null, null); },
+    throws(function() { S.Nothing.reduce(null, null); },
            errorEq(TypeError,
                    'Invalid value\n' +
                    '\n' +
@@ -180,31 +178,31 @@ describe('Nothing', function() {
   });
 
   it('provides a "sequence" method', function() {
-    eq(S.Nothing().sequence.length, 1);
-    eq(S.Nothing().sequence(S.Either.of), S.Right(S.Nothing()));
+    eq(S.Nothing.sequence.length, 1);
+    eq(S.Nothing.sequence(S.Either.of), S.Right(S.Nothing));
   });
 
   it('provides a "toBoolean" method', function() {
-    eq(S.Nothing().toBoolean.length, 0);
-    eq(S.Nothing().toBoolean(), false);
+    eq(S.Nothing.toBoolean.length, 0);
+    eq(S.Nothing.toBoolean(), false);
   });
 
   it('provides a "toString" method', function() {
-    eq(S.Nothing().toString.length, 0);
-    eq(S.Nothing().toString(), 'Nothing()');
+    eq(S.Nothing.toString.length, 0);
+    eq(S.Nothing.toString(), 'Nothing');
   });
 
   it('implements Semigroup', function() {
-    var a = S.Nothing();
-    var b = S.Nothing();
-    var c = S.Nothing();
+    var a = S.Nothing;
+    var b = S.Nothing;
+    var c = S.Nothing;
 
     // associativity
     assert(a.concat(b).concat(c).equals(a.concat(b.concat(c))));
   });
 
   it('implements Monoid', function() {
-    var a = S.Nothing();
+    var a = S.Nothing;
 
     // left identity
     assert(a.empty().concat(a).equals(a));
@@ -214,7 +212,7 @@ describe('Nothing', function() {
   });
 
   it('implements Functor', function() {
-    var a = S.Nothing();
+    var a = S.Nothing;
     var f = S.inc;
     var g = square;
 
@@ -226,9 +224,9 @@ describe('Nothing', function() {
   });
 
   it('implements Apply', function() {
-    var a = S.Nothing();
-    var b = S.Nothing();
-    var c = S.Nothing();
+    var a = S.Nothing;
+    var b = S.Nothing;
+    var c = S.Nothing;
 
     // composition
     assert(a.map(function(f) {
@@ -241,8 +239,8 @@ describe('Nothing', function() {
   });
 
   it('implements Applicative', function() {
-    var a = S.Nothing();
-    var b = S.Nothing();
+    var a = S.Nothing;
+    var b = S.Nothing;
     var f = S.inc;
     var x = 7;
 
@@ -257,7 +255,7 @@ describe('Nothing', function() {
   });
 
   it('implements Chain', function() {
-    var a = S.Nothing();
+    var a = S.Nothing;
     var f = S.head;
     var g = S.last;
 
@@ -267,7 +265,7 @@ describe('Nothing', function() {
   });
 
   it('implements Monad', function() {
-    var a = S.Nothing();
+    var a = S.Nothing;
     var f = S.head;
     var x = [1, 2, 3];
 
diff --git a/test/and.js b/test/and.js
index 0c20fbf..9e9376b 100644
--- a/test/and.js
+++ b/test/and.js
@@ -30,9 +30,9 @@ describe('and', function() {
   });
 
   it('can be applied to maybes', function() {
-    eq(S.and(S.Nothing(), S.Nothing()), S.Nothing());
-    eq(S.and(S.Nothing(), S.Just(42)), S.Nothing());
-    eq(S.and(S.Just(42), S.Nothing()), S.Nothing());
+    eq(S.and(S.Nothing, S.Nothing), S.Nothing);
+    eq(S.and(S.Nothing, S.Just(42)), S.Nothing);
+    eq(S.and(S.Just(42), S.Nothing), S.Nothing);
     eq(S.and(S.Just(42), S.Just(43)), S.Just(43));
   });
 
diff --git a/test/at.js b/test/at.js
index 369b8d2..2f3affa 100644
--- a/test/at.js
+++ b/test/at.js
@@ -48,10 +48,10 @@ describe('at', function() {
     eq(S.at(-1, ['foo', 'bar', 'baz']), S.Just('baz'));
   });
 
-  it('returns a Nothing if index out of bounds', function() {
-    eq(S.at(3, ['foo', 'bar', 'baz']), S.Nothing());
-    eq(S.at(-4, ['foo', 'bar', 'baz']), S.Nothing());
-    eq(S.at(-0, ['foo', 'bar', 'baz']), S.Nothing());
+  it('returns Nothing if index out of bounds', function() {
+    eq(S.at(3, ['foo', 'bar', 'baz']), S.Nothing);
+    eq(S.at(-4, ['foo', 'bar', 'baz']), S.Nothing);
+    eq(S.at(-0, ['foo', 'bar', 'baz']), S.Nothing);
   });
 
   it('is curried', function() {
diff --git a/test/concat.js b/test/concat.js
index 7c46d7d..57fc10a 100644
--- a/test/concat.js
+++ b/test/concat.js
@@ -57,9 +57,9 @@ describe('concat', function() {
   });
 
   it('can be applied to maybes', function() {
-    eq(S.concat(S.Nothing(), S.Nothing()), S.Nothing());
-    eq(S.concat(S.Just('foo'), S.Nothing()), S.Just('foo'));
-    eq(S.concat(S.Nothing(), S.Just('bar')), S.Just('bar'));
+    eq(S.concat(S.Nothing, S.Nothing), S.Nothing);
+    eq(S.concat(S.Just('foo'), S.Nothing), S.Just('foo'));
+    eq(S.concat(S.Nothing, S.Just('bar')), S.Just('bar'));
     eq(S.concat(S.Just('foo'), S.Just('bar')), S.Just('foobar'));
   });
 
diff --git a/test/drop.js b/test/drop.js
index e96a862..4c20687 100644
--- a/test/drop.js
+++ b/test/drop.js
@@ -40,17 +40,17 @@ describe('drop', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing if n is greater than collection length', function() {
-    eq(S.drop(6, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.drop(6, 'abcde'), S.Nothing());
+  it('returns Nothing if n is greater than collection length', function() {
+    eq(S.drop(6, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.drop(6, 'abcde'), S.Nothing);
   });
 
-  it('returns a Nothing if n is negative', function() {
-    eq(S.drop(-3, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.drop(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.drop(-3, 'abcde'), S.Nothing());
-    eq(S.drop(-0, 'abcde'), S.Nothing());
-    eq(S.drop(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+  it('returns Nothing if n is negative', function() {
+    eq(S.drop(-3, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.drop(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.drop(-3, 'abcde'), S.Nothing);
+    eq(S.drop(-0, 'abcde'), S.Nothing);
+    eq(S.drop(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing);
   });
 
   it('returns an empty collection if n is equal to collection length', function() {
diff --git a/test/dropLast.js b/test/dropLast.js
index e32722d..f053ccc 100644
--- a/test/dropLast.js
+++ b/test/dropLast.js
@@ -40,21 +40,21 @@ describe('dropLast', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing if n is negative', function() {
-    eq(S.dropLast(-3, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.dropLast(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.dropLast(-3, 'abcde'), S.Nothing());
-    eq(S.dropLast(-0, 'abcde'), S.Nothing());
-    eq(S.dropLast(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+  it('returns Nothing if n is negative', function() {
+    eq(S.dropLast(-3, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.dropLast(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.dropLast(-3, 'abcde'), S.Nothing);
+    eq(S.dropLast(-0, 'abcde'), S.Nothing);
+    eq(S.dropLast(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing);
   });
 
   it('returns a Just dropping the last n items for valid n; Nothing otherwise', function() {
-    eq(S.dropLast(4, ['a', 'b', 'c']), S.Nothing());
+    eq(S.dropLast(4, ['a', 'b', 'c']), S.Nothing);
     eq(S.dropLast(3, ['a', 'b', 'c']), S.Just([]));
     eq(S.dropLast(2, ['a', 'b', 'c']), S.Just(['a']));
     eq(S.dropLast(1, ['a', 'b', 'c']), S.Just(['a', 'b']));
     eq(S.dropLast(0, ['a', 'b', 'c']), S.Just(['a', 'b', 'c']));
-    eq(S.dropLast(4, 'abc'), S.Nothing());
+    eq(S.dropLast(4, 'abc'), S.Nothing);
     eq(S.dropLast(3, 'abc'), S.Just(''));
     eq(S.dropLast(2, 'abc'), S.Just('a'));
     eq(S.dropLast(1, 'abc'), S.Just('ab'));
diff --git a/test/eitherToMaybe.js b/test/eitherToMaybe.js
index c97e082..28abaf4 100644
--- a/test/eitherToMaybe.js
+++ b/test/eitherToMaybe.js
@@ -28,8 +28,8 @@ describe('eitherToMaybe', function() {
                    'The value at position 1 is not a member of ‘Either a b’.\n'));
   });
 
-  it('returns a Nothing when applied to a Left', function() {
-    eq(S.eitherToMaybe(S.Left('Cannot divide by zero')), S.Nothing());
+  it('returns Nothing when applied to a Left', function() {
+    eq(S.eitherToMaybe(S.Left('Cannot divide by zero')), S.Nothing);
   });
 
   it('returns a Just when applied to a Right', function() {
diff --git a/test/encase.js b/test/encase.js
index c8e4e12..03d9a2c 100644
--- a/test/encase.js
+++ b/test/encase.js
@@ -33,8 +33,8 @@ describe('encase', function() {
     eq(S.encase(factorial, 5), S.Just(120));
   });
 
-  it('returns a Nothing on failure', function() {
-    eq(S.encase(factorial, -1), S.Nothing());
+  it('returns Nothing on failure', function() {
+    eq(S.encase(factorial, -1), S.Nothing);
   });
 
   it('can be applied to a function of arbitrary arity', function() {
diff --git a/test/encase2.js b/test/encase2.js
index 69efdfe..0d73dea 100644
--- a/test/encase2.js
+++ b/test/encase2.js
@@ -34,8 +34,8 @@ describe('encase2', function() {
     eq(S.encase2(rem, 42, 5), S.Just(2));
   });
 
-  it('returns a Nothing on failure', function() {
-    eq(S.encase2(rem, 42, 0), S.Nothing());
+  it('returns Nothing on failure', function() {
+    eq(S.encase2(rem, 42, 0), S.Nothing);
   });
 
   it('can be applied to a function of arbitrary arity', function() {
diff --git a/test/encase2_.js b/test/encase2_.js
index aad19ff..7dfc589 100644
--- a/test/encase2_.js
+++ b/test/encase2_.js
@@ -15,8 +15,8 @@ describe('encase2_', function() {
     eq(S.encase2_(rem, 42, 5), S.Just(2));
   });
 
-  it('returns a Nothing on failure', function() {
-    eq(S.encase2_(rem, 42, 0), S.Nothing());
+  it('returns Nothing on failure', function() {
+    eq(S.encase2_(rem, 42, 0), S.Nothing);
   });
 
 });
diff --git a/test/encase3.js b/test/encase3.js
index 86c01cf..6d56076 100644
--- a/test/encase3.js
+++ b/test/encase3.js
@@ -35,8 +35,8 @@ describe('encase3', function() {
     eq(S.encase3(area, 3, 4, 5), S.Just(6));
   });
 
-  it('returns a Nothing on failure', function() {
-    eq(S.encase3(area, 2, 2, 5), S.Nothing());
+  it('returns Nothing on failure', function() {
+    eq(S.encase3(area, 2, 2, 5), S.Nothing);
   });
 
   it('can be applied to a function of arbitrary arity', function() {
diff --git a/test/encase3_.js b/test/encase3_.js
index 46e1e91..45c07f8 100644
--- a/test/encase3_.js
+++ b/test/encase3_.js
@@ -14,8 +14,8 @@ describe('encase3_', function() {
     eq(S.encase3_(area, 3, 4, 5), S.Just(6));
   });
 
-  it('returns a Nothing on failure', function() {
-    eq(S.encase3_(area, 2, 2, 5), S.Nothing());
+  it('returns Nothing on failure', function() {
+    eq(S.encase3_(area, 2, 2, 5), S.Nothing);
   });
 
 });
diff --git a/test/find.js b/test/find.js
index f52bcb2..8f39233 100644
--- a/test/find.js
+++ b/test/find.js
@@ -46,9 +46,9 @@ describe('find', function() {
     eq(S.find(function(n) { return n >= 0; }, [-1, 0, 1]), S.Just(0));
   });
 
-  it('returns a Nothing if no element satisfies the predicate', function() {
-    eq(S.find(R.T, []), S.Nothing());
-    eq(S.find(R.F, [1, 2, 3]), S.Nothing());
+  it('returns Nothing if no element satisfies the predicate', function() {
+    eq(S.find(R.T, []), S.Nothing);
+    eq(S.find(R.F, [1, 2, 3]), S.Nothing);
   });
 
   it('is curried', function() {
diff --git a/test/fromMaybe.js b/test/fromMaybe.js
index a25ba8c..ce9ec01 100644
--- a/test/fromMaybe.js
+++ b/test/fromMaybe.js
@@ -28,8 +28,8 @@ describe('fromMaybe', function() {
                    'The value at position 1 is not a member of ‘Maybe a’.\n'));
   });
 
-  it('can be applied to a Nothing', function() {
-    eq(S.fromMaybe(0, S.Nothing()), 0);
+  it('can be applied to Nothing', function() {
+    eq(S.fromMaybe(0, S.Nothing), 0);
   });
 
   it('can be applied to a Just', function() {
diff --git a/test/get.js b/test/get.js
index f3fc57e..04e3e6f 100644
--- a/test/get.js
+++ b/test/get.js
@@ -56,8 +56,8 @@ describe('get', function() {
     var obj = {x: 0, y: 42};
     eq(S.get(Number, 'x', obj), S.Just(0));
     eq(S.get(Number, 'y', obj), S.Just(42));
-    eq(S.get(Number, 'z', obj), S.Nothing());
-    eq(S.get(String, 'x', obj), S.Nothing());
+    eq(S.get(Number, 'z', obj), S.Nothing);
+    eq(S.get(String, 'x', obj), S.Nothing);
   });
 
   it('does not rely on constructor identity', function() {
diff --git a/test/gets.js b/test/gets.js
index 3be5832..48e085f 100644
--- a/test/gets.js
+++ b/test/gets.js
@@ -55,12 +55,12 @@ describe('gets', function() {
 
   it('returns a Maybe', function() {
     var obj = {x: {z: 0}, y: 42};
-    eq(S.gets(Number, ['x'], obj), S.Nothing());
+    eq(S.gets(Number, ['x'], obj), S.Nothing);
     eq(S.gets(Number, ['y'], obj), S.Just(42));
-    eq(S.gets(Number, ['z'], obj), S.Nothing());
+    eq(S.gets(Number, ['z'], obj), S.Nothing);
     eq(S.gets(Number, ['x', 'z'], obj), S.Just(0));
-    eq(S.gets(Number, ['a', 'b', 'c'], obj), S.Nothing());
-    eq(S.gets(Number, [], obj), S.Nothing());
+    eq(S.gets(Number, ['a', 'b', 'c'], obj), S.Nothing);
+    eq(S.gets(Number, [], obj), S.Nothing);
     eq(S.gets(Object, [], obj), S.Just({x: {z: 0}, y: 42}));
   });
 
diff --git a/test/head.js b/test/head.js
index 76972c7..92d0e38 100644
--- a/test/head.js
+++ b/test/head.js
@@ -28,8 +28,8 @@ describe('head', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing if applied to empty list', function() {
-    eq(S.head([]), S.Nothing());
+  it('returns Nothing if applied to empty list', function() {
+    eq(S.head([]), S.Nothing);
   });
 
   it('returns Just the head of a nonempty list', function() {
diff --git a/test/indexOf.js b/test/indexOf.js
index d8e68a0..96721ac 100644
--- a/test/indexOf.js
+++ b/test/indexOf.js
@@ -28,12 +28,12 @@ describe('indexOf', function() {
                    '‘indexOf’ requires ‘b’ to satisfy the ArrayLike type-class constraint; the value at position 1 does not.\n'));
   });
 
-  it('returns a Nothing for an empty list', function() {
-    eq(S.indexOf(10, []), S.Nothing());
+  it('returns Nothing for an empty list', function() {
+    eq(S.indexOf(10, []), S.Nothing);
   });
 
-  it('returns a Nothing if the element is not found', function() {
-    eq(S.indexOf('x', ['b', 'a', 'n', 'a', 'n', 'a']), S.Nothing());
+  it('returns Nothing if the element is not found', function() {
+    eq(S.indexOf('x', ['b', 'a', 'n', 'a', 'n', 'a']), S.Nothing);
   });
 
   it('returns Just the index of the element found', function() {
@@ -42,7 +42,7 @@ describe('indexOf', function() {
 
   it('can operate on strings', function() {
     eq(S.indexOf('an', 'banana'), S.Just(1));
-    eq(S.indexOf('ax', 'banana'), S.Nothing());
+    eq(S.indexOf('ax', 'banana'), S.Nothing);
   });
 
   it('is curried', function() {
diff --git a/test/init.js b/test/init.js
index 2846863..fa5e9fb 100644
--- a/test/init.js
+++ b/test/init.js
@@ -28,8 +28,8 @@ describe('init', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing if applied to empty list', function() {
-    eq(S.init([]), S.Nothing());
+  it('returns Nothing if applied to empty list', function() {
+    eq(S.init([]), S.Nothing);
   });
 
   it('returns Just the initial elements of a nonempty list', function() {
diff --git a/test/isJust.js b/test/isJust.js
index 677218d..de133f3 100644
--- a/test/isJust.js
+++ b/test/isJust.js
@@ -32,8 +32,8 @@ describe('isJust', function() {
     eq(S.isJust(S.Just(42)), true);
   });
 
-  it('returns false when applied to a Nothing', function() {
-    eq(S.isJust(S.Nothing()), false);
+  it('returns false when applied to Nothing', function() {
+    eq(S.isJust(S.Nothing), false);
   });
 
 });
diff --git a/test/isNothing.js b/test/isNothing.js
index 036723f..9f2e146 100644
--- a/test/isNothing.js
+++ b/test/isNothing.js
@@ -28,8 +28,8 @@ describe('isNothing', function() {
                    'The value at position 1 is not a member of ‘Maybe a’.\n'));
   });
 
-  it('returns true when applied to a Nothing', function() {
-    eq(S.isNothing(S.Nothing()), true);
+  it('returns true when applied to Nothing', function() {
+    eq(S.isNothing(S.Nothing), true);
   });
 
   it('returns false when applied to a Just', function() {
diff --git a/test/justs.js b/test/justs.js
index 54c91f7..54cd90c 100644
--- a/test/justs.js
+++ b/test/justs.js
@@ -31,9 +31,9 @@ describe('justs', function() {
 
   it('returns a list containing the value of each Just', function() {
     eq(S.justs([]), []);
-    eq(S.justs([S.Nothing(), S.Nothing()]), []);
-    eq(S.justs([S.Nothing(), S.Just('b')]), ['b']);
-    eq(S.justs([S.Just('a'), S.Nothing()]), ['a']);
+    eq(S.justs([S.Nothing, S.Nothing]), []);
+    eq(S.justs([S.Nothing, S.Just('b')]), ['b']);
+    eq(S.justs([S.Just('a'), S.Nothing]), ['a']);
     eq(S.justs([S.Just('a'), S.Just('b')]), ['a', 'b']);
   });
 
diff --git a/test/last.js b/test/last.js
index 8b0fed8..36bf2cb 100644
--- a/test/last.js
+++ b/test/last.js
@@ -28,8 +28,8 @@ describe('last', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing if applied to empty list', function() {
-    eq(S.last([]), S.Nothing());
+  it('returns Nothing if applied to empty list', function() {
+    eq(S.last([]), S.Nothing);
   });
 
   it('returns Just the last element of a nonempty list', function() {
diff --git a/test/lastIndexOf.js b/test/lastIndexOf.js
index 3b74560..10c3adc 100644
--- a/test/lastIndexOf.js
+++ b/test/lastIndexOf.js
@@ -28,12 +28,12 @@ describe('lastIndexOf', function() {
                    '‘lastIndexOf’ requires ‘b’ to satisfy the ArrayLike type-class constraint; the value at position 1 does not.\n'));
   });
 
-  it('returns a Nothing for an empty list', function() {
-    eq(S.lastIndexOf('a', []), S.Nothing());
+  it('returns Nothing for an empty list', function() {
+    eq(S.lastIndexOf('a', []), S.Nothing);
   });
 
-  it('returns a Nothing if the element is not found', function() {
-    eq(S.lastIndexOf('x', ['b', 'a', 'n', 'a', 'n', 'a']), S.Nothing());
+  it('returns Nothing if the element is not found', function() {
+    eq(S.lastIndexOf('x', ['b', 'a', 'n', 'a', 'n', 'a']), S.Nothing);
   });
 
   it('returns Just the last index of the element found', function() {
@@ -42,7 +42,7 @@ describe('lastIndexOf', function() {
 
   it('can operate on strings', function() {
     eq(S.lastIndexOf('an', 'banana'), S.Just(3));
-    eq(S.lastIndexOf('ax', 'banana'), S.Nothing());
+    eq(S.lastIndexOf('ax', 'banana'), S.Nothing);
   });
 
   it('is curried', function() {
diff --git a/test/lift.js b/test/lift.js
index b207c27..9cb36d9 100644
--- a/test/lift.js
+++ b/test/lift.js
@@ -33,7 +33,7 @@ describe('lift2', function() {
     var positive = function(n) { return n > 0; };
 
     eq(S.lift2(S.add, S.Just(3), S.Just(3)), S.Just(6));
-    eq(S.lift2(S.add, S.Nothing(), S.Just(3)), S.Nothing());
+    eq(S.lift2(S.add, S.Nothing, S.Just(3)), S.Nothing);
 
     eq(S.lift2(S.add, S.Right(3), S.Left(4)), S.Left(4));
     eq(S.lift2(S.add, S.Right(3), S.Right(4)), S.Right(7));
diff --git a/test/lift2.js b/test/lift2.js
index e457026..01f8bf6 100644
--- a/test/lift2.js
+++ b/test/lift2.js
@@ -30,7 +30,7 @@ describe('lift', function() {
 
   it('lifts a function into the context of Functors', function() {
     eq(S.lift(S.mult(2), S.Just(3)), S.Just(6));
-    eq(S.lift(S.mult(2), S.Nothing()), S.Nothing());
+    eq(S.lift(S.mult(2), S.Nothing), S.Nothing);
 
     eq(S.lift(S.mult(2), S.Left(3)), S.Left(3));
     eq(S.lift(S.mult(2), S.Right(3)), S.Right(6));
diff --git a/test/lift3.js b/test/lift3.js
index e3807e6..ae489b0 100644
--- a/test/lift3.js
+++ b/test/lift3.js
@@ -32,7 +32,7 @@ describe('lift3', function() {
 
   it('lifts a function into the context of Applys', function() {
     eq(S.lift3(S.reduce, S.Just(S.add), S.Just(0), S.Just([1, 2, 3])), S.Just(6));
-    eq(S.lift3(S.reduce, S.Just(S.add), S.Just(0), S.Nothing()), S.Nothing());
+    eq(S.lift3(S.reduce, S.Just(S.add), S.Just(0), S.Nothing), S.Nothing);
 
     eq(S.lift3(S.reduce, S.Right(S.add), S.Right(0), S.Right([1, 2, 3])), S.Right(6));
     eq(S.lift3(S.reduce, S.Right(S.add), S.Right(0), S.Left('WHOOPS')), S.Left('WHOOPS'));
diff --git a/test/match.js b/test/match.js
index e4daa7e..cd31b21 100644
--- a/test/match.js
+++ b/test/match.js
@@ -53,11 +53,11 @@ describe('match', function() {
     eq(S.match(/(good)?bye/, 'goodbye'),
        S.Just([S.Just('goodbye'), S.Just('good')]));
     eq(S.match(/(good)?bye/, 'bye'),
-       S.Just([S.Just('bye'), S.Nothing()]));
+       S.Just([S.Just('bye'), S.Nothing]));
   });
 
-  it('returns a Nothing if no match', function() {
-    eq(S.match(/zzz/, 'abcdefg'), S.Nothing());
+  it('returns Nothing if no match', function() {
+    eq(S.match(/zzz/, 'abcdefg'), S.Nothing);
   });
 
   it('is curried', function() {
diff --git a/test/maybe.js b/test/maybe.js
index 9b20fd5..6e7de6c 100644
--- a/test/maybe.js
+++ b/test/maybe.js
@@ -44,8 +44,8 @@ describe('maybe', function() {
                    'The value at position 1 is not a member of ‘Maybe a’.\n'));
   });
 
-  it('can be applied to a Nothing', function() {
-    eq(S.maybe(0, R.length, S.Nothing()), 0);
+  it('can be applied to Nothing', function() {
+    eq(S.maybe(0, R.length, S.Nothing), 0);
   });
 
   it('can be applied to a Just', function() {
diff --git a/test/maybeToEither.js b/test/maybeToEither.js
index 9b0b7b6..1f18a76 100644
--- a/test/maybeToEither.js
+++ b/test/maybeToEither.js
@@ -29,7 +29,7 @@ describe('maybeToEither', function() {
   });
 
   it('returns a Left of its first argument when the second is Nothing', function() {
-    eq(S.maybeToEither('error msg', S.Nothing()), S.Left('error msg'));
+    eq(S.maybeToEither('error msg', S.Nothing), S.Left('error msg'));
   });
 
   it('returns a Right of the value contained in the Just when the second argument is a Just', function() {
diff --git a/test/maybeToNullable.js b/test/maybeToNullable.js
index 762d884..e1d7c98 100644
--- a/test/maybeToNullable.js
+++ b/test/maybeToNullable.js
@@ -28,8 +28,8 @@ describe('maybeToNullable', function() {
                    'The value at position 1 is not a member of ‘Maybe a’.\n'));
   });
 
-  it('can be applied to a Nothing', function() {
-    eq(S.maybeToNullable(S.Nothing()), null);
+  it('can be applied to Nothing', function() {
+    eq(S.maybeToNullable(S.Nothing), null);
   });
 
   it('can be applied to a Just', function() {
diff --git a/test/mean.js b/test/mean.js
index ad6dc6c..308f11c 100644
--- a/test/mean.js
+++ b/test/mean.js
@@ -59,17 +59,17 @@ describe('mean', function() {
     eq(S.mean([-0, 0]), S.Just(0));
   });
 
-  it('returns nothing when applied to an empty array', function() {
-    eq(S.mean([]), S.Nothing());
+  it('returns Nothing when applied to an empty array', function() {
+    eq(S.mean([]), S.Nothing);
   });
 
-  it('can be applied to Maybes', function() {
-    eq(S.mean(S.Nothing()), S.Nothing());
+  it('can be applied to maybes', function() {
+    eq(S.mean(S.Nothing), S.Nothing);
     eq(S.mean(S.Just(42)), S.Just(42));
   });
 
-  it('can be applied to Eithers', function() {
-    eq(S.mean(S.Left('xxx')), S.Nothing());
+  it('can be applied to eithers', function() {
+    eq(S.mean(S.Left('xxx')), S.Nothing);
     eq(S.mean(S.Right(42)), S.Just(42));
   });
 
diff --git a/test/or.js b/test/or.js
index 08edd5f..02a2acd 100644
--- a/test/or.js
+++ b/test/or.js
@@ -30,9 +30,9 @@ describe('or', function() {
   });
 
   it('can be applied to maybes', function() {
-    eq(S.or(S.Nothing(), S.Nothing()), S.Nothing());
-    eq(S.or(S.Nothing(), S.Just(42)), S.Just(42));
-    eq(S.or(S.Just(42), S.Nothing()), S.Just(42));
+    eq(S.or(S.Nothing, S.Nothing), S.Nothing);
+    eq(S.or(S.Nothing, S.Just(42)), S.Just(42));
+    eq(S.or(S.Just(42), S.Nothing), S.Just(42));
     eq(S.or(S.Just(42), S.Just(43)), S.Just(42));
   });
 
diff --git a/test/parseDate.js b/test/parseDate.js
index 9a9ce2c..de30ffa 100644
--- a/test/parseDate.js
+++ b/test/parseDate.js
@@ -33,8 +33,8 @@ describe('parseDate', function() {
        S.Just(new Date('2001-02-03T04:05:06Z')));
   });
 
-  it('returns a Nothing when applied to an invalid date string', function() {
-    eq(S.parseDate('today'), S.Nothing());
+  it('returns Nothing when applied to an invalid date string', function() {
+    eq(S.parseDate('today'), S.Nothing);
   });
 
 });
diff --git a/test/parseFloat.js b/test/parseFloat.js
index 07fd5ca..cf93bbb 100644
--- a/test/parseFloat.js
+++ b/test/parseFloat.js
@@ -50,15 +50,15 @@ describe('parseFloat', function() {
     eq(S.parseFloat('-.25'), S.Just(-0.25));
     eq(S.parseFloat('0.5 '), S.Just(0.5));
     eq(S.parseFloat(' 0.5'), S.Just(0.5));
-    eq(S.parseFloat('0.5x'), S.Nothing());  // parseFloat('0.5x') == 0.25
-    eq(S.parseFloat('x0.5'), S.Nothing());
+    eq(S.parseFloat('0.5x'), S.Nothing);  // parseFloat('0.5x') == 0.25
+    eq(S.parseFloat('x0.5'), S.Nothing);
     eq(S.parseFloat('-1e3'), S.Just(-1000));
     eq(S.parseFloat('-1e03'), S.Just(-1000));
     eq(S.parseFloat('-1e+3'), S.Just(-1000));
     eq(S.parseFloat('-1e+03'), S.Just(-1000));
     eq(S.parseFloat('-1e-3'), S.Just(-0.001));
     eq(S.parseFloat('-1e-03'), S.Just(-0.001));
-    eq(S.parseFloat('xxx'), S.Nothing());
+    eq(S.parseFloat('xxx'), S.Nothing);
   });
 
 });
diff --git a/test/parseInt.js b/test/parseInt.js
index b1396fb..e14db4e 100644
--- a/test/parseInt.js
+++ b/test/parseInt.js
@@ -43,81 +43,81 @@ describe('parseInt', function() {
   it('returns a Maybe', function() {
     eq(S.parseInt(10, '42'), S.Just(42));
     eq(S.parseInt(16, '2A'), S.Just(42));
-    eq(S.parseInt(10, 'NaN'), S.Nothing());
-    eq(S.parseInt(10, 'xxx'), S.Nothing());
+    eq(S.parseInt(10, 'NaN'), S.Nothing);
+    eq(S.parseInt(10, 'xxx'), S.Nothing);
   });
 
   it('accepts radix in [2 .. 36]', function() {
     eq(S.parseInt(2, '1'), S.Just(1));
-    eq(S.parseInt(2, '2'), S.Nothing());
+    eq(S.parseInt(2, '2'), S.Nothing);
     eq(S.parseInt(3, '2'), S.Just(2));
-    eq(S.parseInt(3, '3'), S.Nothing());
+    eq(S.parseInt(3, '3'), S.Nothing);
     eq(S.parseInt(4, '3'), S.Just(3));
-    eq(S.parseInt(4, '4'), S.Nothing());
+    eq(S.parseInt(4, '4'), S.Nothing);
     eq(S.parseInt(5, '4'), S.Just(4));
-    eq(S.parseInt(5, '5'), S.Nothing());
+    eq(S.parseInt(5, '5'), S.Nothing);
     eq(S.parseInt(6, '5'), S.Just(5));
-    eq(S.parseInt(6, '6'), S.Nothing());
+    eq(S.parseInt(6, '6'), S.Nothing);
     eq(S.parseInt(7, '6'), S.Just(6));
-    eq(S.parseInt(7, '7'), S.Nothing());
+    eq(S.parseInt(7, '7'), S.Nothing);
     eq(S.parseInt(8, '7'), S.Just(7));
-    eq(S.parseInt(8, '8'), S.Nothing());
+    eq(S.parseInt(8, '8'), S.Nothing);
     eq(S.parseInt(9, '8'), S.Just(8));
-    eq(S.parseInt(9, '9'), S.Nothing());
+    eq(S.parseInt(9, '9'), S.Nothing);
     eq(S.parseInt(10, '9'), S.Just(9));
-    eq(S.parseInt(10, 'A'), S.Nothing());
+    eq(S.parseInt(10, 'A'), S.Nothing);
     eq(S.parseInt(11, 'A'), S.Just(10));
-    eq(S.parseInt(11, 'B'), S.Nothing());
+    eq(S.parseInt(11, 'B'), S.Nothing);
     eq(S.parseInt(12, 'B'), S.Just(11));
-    eq(S.parseInt(12, 'C'), S.Nothing());
+    eq(S.parseInt(12, 'C'), S.Nothing);
     eq(S.parseInt(13, 'C'), S.Just(12));
-    eq(S.parseInt(13, 'D'), S.Nothing());
+    eq(S.parseInt(13, 'D'), S.Nothing);
     eq(S.parseInt(14, 'D'), S.Just(13));
-    eq(S.parseInt(14, 'E'), S.Nothing());
+    eq(S.parseInt(14, 'E'), S.Nothing);
     eq(S.parseInt(15, 'E'), S.Just(14));
-    eq(S.parseInt(15, 'F'), S.Nothing());
+    eq(S.parseInt(15, 'F'), S.Nothing);
     eq(S.parseInt(16, 'F'), S.Just(15));
-    eq(S.parseInt(16, 'G'), S.Nothing());
+    eq(S.parseInt(16, 'G'), S.Nothing);
     eq(S.parseInt(17, 'G'), S.Just(16));
-    eq(S.parseInt(17, 'H'), S.Nothing());
+    eq(S.parseInt(17, 'H'), S.Nothing);
     eq(S.parseInt(18, 'H'), S.Just(17));
-    eq(S.parseInt(18, 'I'), S.Nothing());
+    eq(S.parseInt(18, 'I'), S.Nothing);
     eq(S.parseInt(19, 'I'), S.Just(18));
-    eq(S.parseInt(19, 'J'), S.Nothing());
+    eq(S.parseInt(19, 'J'), S.Nothing);
     eq(S.parseInt(20, 'J'), S.Just(19));
-    eq(S.parseInt(20, 'K'), S.Nothing());
+    eq(S.parseInt(20, 'K'), S.Nothing);
     eq(S.parseInt(21, 'K'), S.Just(20));
-    eq(S.parseInt(21, 'L'), S.Nothing());
+    eq(S.parseInt(21, 'L'), S.Nothing);
     eq(S.parseInt(22, 'L'), S.Just(21));
-    eq(S.parseInt(22, 'M'), S.Nothing());
+    eq(S.parseInt(22, 'M'), S.Nothing);
     eq(S.parseInt(23, 'M'), S.Just(22));
-    eq(S.parseInt(23, 'N'), S.Nothing());
+    eq(S.parseInt(23, 'N'), S.Nothing);
     eq(S.parseInt(24, 'N'), S.Just(23));
-    eq(S.parseInt(24, 'O'), S.Nothing());
+    eq(S.parseInt(24, 'O'), S.Nothing);
     eq(S.parseInt(25, 'O'), S.Just(24));
-    eq(S.parseInt(25, 'P'), S.Nothing());
+    eq(S.parseInt(25, 'P'), S.Nothing);
     eq(S.parseInt(26, 'P'), S.Just(25));
-    eq(S.parseInt(26, 'Q'), S.Nothing());
+    eq(S.parseInt(26, 'Q'), S.Nothing);
     eq(S.parseInt(27, 'Q'), S.Just(26));
-    eq(S.parseInt(27, 'R'), S.Nothing());
+    eq(S.parseInt(27, 'R'), S.Nothing);
     eq(S.parseInt(28, 'R'), S.Just(27));
-    eq(S.parseInt(28, 'S'), S.Nothing());
+    eq(S.parseInt(28, 'S'), S.Nothing);
     eq(S.parseInt(29, 'S'), S.Just(28));
-    eq(S.parseInt(29, 'T'), S.Nothing());
+    eq(S.parseInt(29, 'T'), S.Nothing);
     eq(S.parseInt(30, 'T'), S.Just(29));
-    eq(S.parseInt(30, 'U'), S.Nothing());
+    eq(S.parseInt(30, 'U'), S.Nothing);
     eq(S.parseInt(31, 'U'), S.Just(30));
-    eq(S.parseInt(31, 'V'), S.Nothing());
+    eq(S.parseInt(31, 'V'), S.Nothing);
     eq(S.parseInt(32, 'V'), S.Just(31));
-    eq(S.parseInt(32, 'W'), S.Nothing());
+    eq(S.parseInt(32, 'W'), S.Nothing);
     eq(S.parseInt(33, 'W'), S.Just(32));
-    eq(S.parseInt(33, 'X'), S.Nothing());
+    eq(S.parseInt(33, 'X'), S.Nothing);
     eq(S.parseInt(34, 'X'), S.Just(33));
-    eq(S.parseInt(34, 'Y'), S.Nothing());
+    eq(S.parseInt(34, 'Y'), S.Nothing);
     eq(S.parseInt(35, 'Y'), S.Just(34));
-    eq(S.parseInt(35, 'Z'), S.Nothing());
+    eq(S.parseInt(35, 'Z'), S.Nothing);
     eq(S.parseInt(36, 'Z'), S.Just(35));
-    eq(S.parseInt(36, '['), S.Nothing());
+    eq(S.parseInt(36, '['), S.Nothing);
   });
 
   it('throws if radix is not in [2 .. 36]', function() {
@@ -145,26 +145,26 @@ describe('parseInt', function() {
   it('accepts optional "0x" or "0X" prefix when radix is 16', function() {
     eq(S.parseInt(16, '0xFF'), S.Just(255));
     eq(S.parseInt(16, '0XFF'), S.Just(255));
-    eq(S.parseInt(17, '0xFF'), S.Nothing());
-    eq(S.parseInt(17, '0XFF'), S.Nothing());
+    eq(S.parseInt(17, '0xFF'), S.Nothing);
+    eq(S.parseInt(17, '0XFF'), S.Nothing);
     eq(S.parseInt(16, '+0xFF'), S.Just(255));
     eq(S.parseInt(16, '+0XFF'), S.Just(255));
     eq(S.parseInt(16, '-0xFF'), S.Just(-255));
     eq(S.parseInt(16, '-0XFF'), S.Just(-255));
   });
 
-  it('returns a Nothing if one or more characters are invalid', function() {
-    eq(S.parseInt(10, '12.34'), S.Nothing());  // parseInt('12.34', 10) == 12
-    eq(S.parseInt(16, 'alice'), S.Nothing());  // parseInt('alice', 16) == 10
+  it('returns Nothing if one or more characters are invalid', function() {
+    eq(S.parseInt(10, '12.34'), S.Nothing);  // parseInt('12.34', 10) == 12
+    eq(S.parseInt(16, 'alice'), S.Nothing);  // parseInt('alice', 16) == 10
   });
 
   it('restricts to exactly representable range (-2^53 .. 2^53)', function() {
     eq(S.parseInt(10,  '9007199254740991'), S.Just(9007199254740991));
     eq(S.parseInt(10, '-9007199254740991'), S.Just(-9007199254740991));
-    eq(S.parseInt(10,  '9007199254740992'), S.Nothing());
-    eq(S.parseInt(10, '-9007199254740992'), S.Nothing());
-    eq(S.parseInt(10,  'Infinity'), S.Nothing());
-    eq(S.parseInt(10, '-Infinity'), S.Nothing());
+    eq(S.parseInt(10,  '9007199254740992'), S.Nothing);
+    eq(S.parseInt(10, '-9007199254740992'), S.Nothing);
+    eq(S.parseInt(10,  'Infinity'), S.Nothing);
+    eq(S.parseInt(10, '-Infinity'), S.Nothing);
   });
 
   it('is curried', function() {
diff --git a/test/parseJson.js b/test/parseJson.js
index 1c25b34..506aadb 100644
--- a/test/parseJson.js
+++ b/test/parseJson.js
@@ -44,12 +44,12 @@ describe('parseJson', function() {
     eq(S.parseJson(Array, '["foo","bar"]'), S.Just(['foo', 'bar']));
   });
 
-  it('returns a Nothing when applied to an invalid JSON string', function() {
-    eq(S.parseJson(Object, '[Invalid JSON]'), S.Nothing());
+  it('returns Nothing when applied to an invalid JSON string', function() {
+    eq(S.parseJson(Object, '[Invalid JSON]'), S.Nothing);
   });
 
-  it('returns a Nothing when the parsed result is not a member of the given type', function() {
-    eq(S.parseJson(Array, '{"foo":"bar"}'), S.Nothing());
+  it('returns Nothing when the parsed result is not a member of the given type', function() {
+    eq(S.parseJson(Array, '{"foo":"bar"}'), S.Nothing);
   });
 
 });
diff --git a/test/pluck.js b/test/pluck.js
index 84e4eb8..8692123 100644
--- a/test/pluck.js
+++ b/test/pluck.js
@@ -57,7 +57,7 @@ describe('pluck', function() {
     var xs = [{x: '1'}, {x: 2}, {x: null}, {x: undefined}, {}];
     eq(S.pluck(Number, 'x', []), []);
     eq(S.pluck(Number, 'x', xs),
-       [S.Nothing(), S.Just(2), S.Nothing(), S.Nothing(), S.Nothing()]);
+       [S.Nothing, S.Just(2), S.Nothing, S.Nothing, S.Nothing]);
   });
 
   it('does not rely on constructor identity', function() {
diff --git a/test/product.js b/test/product.js
index 8d1bde0..e996bed 100644
--- a/test/product.js
+++ b/test/product.js
@@ -72,12 +72,12 @@ describe('product', function() {
     eq(S.product([1, 2, 3, 4, -5]), -120);
   });
 
-  it('can be applied to Maybes', function() {
-    eq(S.product(S.Nothing()), 1);
+  it('can be applied to maybes', function() {
+    eq(S.product(S.Nothing), 1);
     eq(S.product(S.Just(42)), 42);
   });
 
-  it('can be applied to Eithers', function() {
+  it('can be applied to eithers', function() {
     eq(S.product(S.Left('xxx')), 1);
     eq(S.product(S.Right(42)), 42);
   });
diff --git a/test/slice.js b/test/slice.js
index c116a79..b9b6155 100644
--- a/test/slice.js
+++ b/test/slice.js
@@ -52,20 +52,20 @@ describe('slice', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing with a positive end index greater than start index', function() {
-    eq(S.slice(6, 1, [1, 2, 3, 4, 5]), S.Nothing());
+  it('returns Nothing with a positive end index greater than start index', function() {
+    eq(S.slice(6, 1, [1, 2, 3, 4, 5]), S.Nothing);
   });
 
-  it('returns a Nothing with a positive end index greater than list length', function() {
-    eq(S.slice(1, 6, [1, 2, 3, 4, 5]), S.Nothing());
+  it('returns Nothing with a positive end index greater than list length', function() {
+    eq(S.slice(1, 6, [1, 2, 3, 4, 5]), S.Nothing);
   });
 
-  it('returns a Nothing with a negative end index greater than list length', function() {
-    eq(S.slice(1, -6, [1, 2, 3, 4, 5]), S.Nothing());
+  it('returns Nothing with a negative end index greater than list length', function() {
+    eq(S.slice(1, -6, [1, 2, 3, 4, 5]), S.Nothing);
   });
 
-  it('returns a Nothing with a negative start index greater than list length', function() {
-    eq(S.slice(-6, 1, [1, 2, 3, 4, 5]), S.Nothing());
+  it('returns Nothing with a negative start index greater than list length', function() {
+    eq(S.slice(-6, 1, [1, 2, 3, 4, 5]), S.Nothing);
   });
 
   it('returns a Just with an empty array when start index equals end index', function() {
@@ -106,7 +106,7 @@ describe('slice', function() {
     eq(S.slice(0, -0, 'ramda'), S.Just('ramda'));
     eq(S.slice(1, -3, 'ramda'), S.Just('a'));
     eq(S.slice(2, -3, 'ramda'), S.Just(''));
-    eq(S.slice(3, -3, 'ramda'), S.Nothing());
+    eq(S.slice(3, -3, 'ramda'), S.Nothing);
   });
 
   it('is curried', function() {
diff --git a/test/sum.js b/test/sum.js
index 4ac6fe2..04d98a9 100644
--- a/test/sum.js
+++ b/test/sum.js
@@ -72,12 +72,12 @@ describe('sum', function() {
     eq(S.sum([1, 2, 3, 4, -5]), 5);
   });
 
-  it('can be applied to Maybes', function() {
-    eq(S.sum(S.Nothing()), 0);
+  it('can be applied to maybes', function() {
+    eq(S.sum(S.Nothing), 0);
     eq(S.sum(S.Just(42)), 42);
   });
 
-  it('can be applied to Eithers', function() {
+  it('can be applied to eithers', function() {
     eq(S.sum(S.Left('xxx')), 0);
     eq(S.sum(S.Right(42)), 42);
   });
diff --git a/test/tail.js b/test/tail.js
index 8174a0a..ecc2b01 100644
--- a/test/tail.js
+++ b/test/tail.js
@@ -28,8 +28,8 @@ describe('tail', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing if applied to empty list', function() {
-    eq(S.tail([]), S.Nothing());
+  it('returns Nothing if applied to empty list', function() {
+    eq(S.tail([]), S.Nothing);
   });
 
   it('returns Just the tail of a nonempty list', function() {
diff --git a/test/take.js b/test/take.js
index 3676d49..1d61599 100644
--- a/test/take.js
+++ b/test/take.js
@@ -39,17 +39,17 @@ describe('take', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing if n is greater than collection length', function() {
-    eq(S.take(6, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.take(6, 'abcde'), S.Nothing());
+  it('returns Nothing if n is greater than collection length', function() {
+    eq(S.take(6, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.take(6, 'abcde'), S.Nothing);
   });
 
-  it('returns a Nothing if n is negative', function() {
-    eq(S.take(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.take(-1, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.take(-0, 'abcdefg'), S.Nothing());
-    eq(S.take(-1, 'abcde'), S.Nothing());
-    eq(S.take(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+  it('returns Nothing if n is negative', function() {
+    eq(S.take(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.take(-1, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.take(-0, 'abcdefg'), S.Nothing);
+    eq(S.take(-1, 'abcde'), S.Nothing);
+    eq(S.take(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing);
   });
 
   it('returns an empty collection if n is 0', function() {
diff --git a/test/takeLast.js b/test/takeLast.js
index a196893..2cc3cc9 100644
--- a/test/takeLast.js
+++ b/test/takeLast.js
@@ -39,21 +39,21 @@ describe('takeLast', function() {
                    'The value at position 1 is not a member of ‘List a’.\n'));
   });
 
-  it('returns a Nothing if n is negative', function() {
-    eq(S.takeLast(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.takeLast(-1, ['a', 'b', 'c', 'd', 'e']), S.Nothing());
-    eq(S.takeLast(-0, 'abcde'), S.Nothing());
-    eq(S.takeLast(-1, 'abcde'), S.Nothing());
-    eq(S.takeLast(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing());
+  it('returns Nothing if n is negative', function() {
+    eq(S.takeLast(-0, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.takeLast(-1, ['a', 'b', 'c', 'd', 'e']), S.Nothing);
+    eq(S.takeLast(-0, 'abcde'), S.Nothing);
+    eq(S.takeLast(-1, 'abcde'), S.Nothing);
+    eq(S.takeLast(new Number(-0), ['a', 'b', 'c', 'd', 'e']), S.Nothing);
   });
 
   it('returns a Just with the last n elements for valid n; Nothing otherwise', function() {
-    eq(S.takeLast(4, ['a', 'b', 'c']), S.Nothing());
+    eq(S.takeLast(4, ['a', 'b', 'c']), S.Nothing);
     eq(S.takeLast(3, ['a', 'b', 'c']), S.Just(['a', 'b', 'c']));
     eq(S.takeLast(2, ['a', 'b', 'c']), S.Just(['b', 'c']));
     eq(S.takeLast(1, ['a', 'b', 'c']), S.Just(['c']));
     eq(S.takeLast(0, ['a', 'b', 'c']), S.Just([]));
-    eq(S.takeLast(4, 'abc'), S.Nothing());
+    eq(S.takeLast(4, 'abc'), S.Nothing);
     eq(S.takeLast(3, 'abc'), S.Just('abc'));
     eq(S.takeLast(2, 'abc'), S.Just('bc'));
     eq(S.takeLast(1, 'abc'), S.Just('c'));
diff --git a/test/toMaybe.js b/test/toMaybe.js
index 0efc47b..aa706e3 100644
--- a/test/toMaybe.js
+++ b/test/toMaybe.js
@@ -11,9 +11,9 @@ describe('toMaybe', function() {
     eq(S.toMaybe.length, 1);
   });
 
-  it('returns a Nothing when applied to null/undefined', function() {
-    eq(S.toMaybe(null), S.Nothing());
-    eq(S.toMaybe(undefined), S.Nothing());
+  it('returns Nothing when applied to null/undefined', function() {
+    eq(S.toMaybe(null), S.Nothing);
+    eq(S.toMaybe(undefined), S.Nothing);
   });
 
   it('returns a Just when applied to any other value', function() {
diff --git a/test/type.js b/test/type.js
index 7891e25..e75d787 100644
--- a/test/type.js
+++ b/test/type.js
@@ -34,7 +34,7 @@ describe('type', function() {
   it('operates on values of Sanctuary types', function() {
     eq(S.type(S.Left(42)),  'sanctuary/Either');
     eq(S.type(S.Right(42)), 'sanctuary/Either');
-    eq(S.type(S.Nothing()), 'sanctuary/Maybe');
+    eq(S.type(S.Nothing), 'sanctuary/Maybe');
     eq(S.type(S.Just(42)),  'sanctuary/Maybe');
   });
 
diff --git a/test/unfolr.js b/test/unfolr.js
index 6659d04..cfcc493 100644
--- a/test/unfolr.js
+++ b/test/unfolr.js
@@ -30,7 +30,7 @@ describe('unfoldr', function() {
 
   it('correctly unfolds a value into a list', function() {
     var f = function(n) {
-      return n >= 5 ? S.Nothing() : S.Just([n, n + 1]);
+      return n >= 5 ? S.Nothing : S.Just([n, n + 1]);
     };
     eq(S.unfoldr(f, 5), []);
     eq(S.unfoldr(f, 4), [4]);
diff --git a/test/xor.js b/test/xor.js
index c39047d..48c1aba 100644
--- a/test/xor.js
+++ b/test/xor.js
@@ -30,10 +30,10 @@ describe('xor', function() {
   });
 
   it('can be applied to maybes', function() {
-    eq(S.xor(S.Nothing(), S.Nothing()), S.Nothing());
-    eq(S.xor(S.Nothing(), S.Just(42)), S.Just(42));
-    eq(S.xor(S.Just(42), S.Nothing()), S.Just(42));
-    eq(S.xor(S.Just(42), S.Just(43)), S.Nothing());
+    eq(S.xor(S.Nothing, S.Nothing), S.Nothing);
+    eq(S.xor(S.Nothing, S.Just(42)), S.Just(42));
+    eq(S.xor(S.Just(42), S.Nothing), S.Just(42));
+    eq(S.xor(S.Just(42), S.Just(43)), S.Nothing);
   });
 
   it('cannot be applied to eithers', function() {