docs: function makeMaybe(inValues, makeChildType) {
  
  
  	var maybeUniverse = new is.In(inValues);
  
  	function Maybe(values) {
  
  		// Maybe has two sub-sets:
  		// - `.range` - Selects the non-enum values. Ex: `GreaterThan(3)`
  		// - `.enum` - Selects the enum values. This is ALWAYS an `In`. Ex: `In([null])`.
  		// Maybe is effectively an OR with these two properties.
  		var result = splitByRangeAndEnum(maybeUniverse, values.range);
  		this.range = result.range || set.EMPTY;
  		if (values.enum) {
  			if (result.enum !== set.EMPTY) {
  				this.enum = set.union(result.enum, values.enum);
  			} else {
  				this.enum = values.enum;
  			}
  		} else {
  			this.enum = result.enum;
  		}
  		if(this.enum === set.EMPTY && this.range === set.EMPTY) {
  			return set.EMPTY;
  		}
  	}
  	Maybe.prototype.orValues = function() {
  		var values = [];
  		if( this.range !== set.EMPTY ) {
  			values.push(this.range);
  		}
  		if( this.enum !== set.EMPTY ) {
  			values.push(this.enum);
  		}
  		return values;
  	};
  	Maybe.prototype[isMemberSymbol] = function isMember() {
  		var rangeIsMember = this.range[isMemberSymbol] || this.range.isMember,
  			enumIsMember = this.enum[isMemberSymbol] || this.enum.isMember;
  		return rangeIsMember.apply(this.range, arguments) || enumIsMember.apply(this.enum, arguments);
  	}
  
  
  
  	set.defineComparison(Maybe, Maybe, {
  		union: function(maybeA, maybeB) {
  			var enumSet = set.union(maybeA.enum, maybeB.enum);
  			var range = set.union(maybeA.range, maybeB.range);
  
  			return new Maybe({
  				enum: enumSet,
  				range: range
  			});
  		},
  		difference: function(maybeA, maybeB) {
  			var enumSet = set.difference(maybeA.enum, maybeB.enum);
  			var range = set.difference(maybeA.range, maybeB.range);
  
  			return new Maybe({
  				enum: enumSet,
  				range: range
  			});
  		},
  		intersection: function(maybeA, maybeB) {
  			var enumSet = set.intersection(maybeA.enum, maybeB.enum);
  			var range = set.intersection(maybeA.range, maybeB.range);
  
  			return new Maybe({
  				enum: enumSet,
  				range: range
  			});
  		}
  	});
  	Maybe.inValues = inValues;
  
  	set.defineComparison(set.UNIVERSAL, Maybe, {
  		difference: function(universe, maybe) {
  			var primary,
  				secondary;
  
  			if (maybe.range === set.UNIVERSAL) {
  				// there is only the enum
  				return new Maybe({
  					range: maybe.range,
  					enum: set.difference(maybeUniverse, maybe.enum)
  				});
  			}
  			// there is only a primary
  			if (maybe.enum === set.EMPTY) {
  				var rangeSet = set.difference(set.UNIVERSAL, maybe.range);
  				var notPresent = set.difference(maybeUniverse, maybe.range);
  				// make sure they are included
  				var enumSet = set.difference(notPresent, rangeSet);
  
  
  				return new Maybe({
  					range: rangeSet,
  					enum: enumSet
  				});
  				// check enum things that aren't included in primary
  
  			} else {
  				primary = set.difference(universe, maybe.range);
  				secondary = set.difference(maybeUniverse, maybe.enum);
  			}
  			return new Maybe({
  				enum: secondary,
  				range: primary
  			});
  		}
  	});
  	makeChildType = makeChildType || function(v) {
  		return v;
  	}
  
  	Maybe.hydrate = function(value, childHydrate) {
  		return new Maybe({
  			range: childHydrate(value, makeChildType)
  		});
  	};
  
  	return Maybe;
  }