Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

sanctuary

Package Overview
Dependencies
Maintainers
1
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

sanctuary - npm Package Compare versions

Comparing version 0.4.0 to 0.5.0

1125

index.js

@@ -11,2 +11,55 @@ /* #######

//. # Sanctuary
//.
//. Sanctuary is a small functional programming library inspired by Haskell
//. and PureScript. It depends on and works nicely with [Ramda][]. Sanctuary
//. makes it possible to write safe code without null checks.
//.
//. In JavaScript it's trivial to introduce a possible run-time type error:
//.
//. words[0].toUpperCase()
//.
//. If `words` is `[]` we'll get a familiar error at run-time:
//.
//. TypeError: Cannot read property 'toUpperCase' of undefined
//.
//. Sanctuary gives us a fighting chance of avoiding such errors. We might
//. write:
//.
//. R.map(R.toUpper, S.head(words))
//.
//. ## Types
//.
//. Sanctuary uses Haskell-like type signatures to describe the types of
//. values, including functions. `'foo'`, for example, has type `String`;
//. `[1, 2, 3]` has type `[Number]`. The arrow (`->`) is used to express a
//. function's type. `Math.abs`, for example, has type `Number -> Number`.
//. That is, it takes an argument of type `Number` and returns a value of
//. type `Number`.
//.
//. [`R.map`][R.map] has type `(a -> b) -> [a] -> [b]`. That is, it takes
//. an argument of type `a -> b` and returns a value of type `[a] -> [b]`.
//. `a` and `b` are type variables: applying `R.map` to a value of type
//. `String -> Number` will give a value of type `[String] -> [Number]`.
//.
//. Sanctuary embraces types. JavaScript doesn't support algebraic data types,
//. but these can be simulated by providing a group of constructor functions
//. whose prototypes provide the same set of methods. A value of the Maybe
//. type, for example, is created via the Nothing constructor or the Just
//. 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,
//. the `map` method takes an implicit argument `x` in addition to the explicit
//. argument `y`. The type of the value upon which a method is invoked appears
//. at the beginning of the signature, separated from the arguments and return
//. value by a squiggly arrow (`~>`). The type of the `map` method of the Maybe
//. type is written `Maybe a ~> (a -> b) -> Maybe b`. One could read this as:
//.
//. _When the `map` method is invoked on a value of type `Maybe a`
//. (for any type `a`) with an argument of type `a -> b` (for any type `b`),
//. it returns a value of type `Maybe b`._
//.
//. ## API
;(function() {

@@ -16,20 +69,15 @@

var hasOwnProperty_ = Object.prototype.hasOwnProperty;
var slice_ = Array.prototype.slice;
var toString_ = Object.prototype.toString;
var R;
var S = {};
var isArray = function(x) {
return toString_.call(x) === '[object Array]';
};
/* istanbul ignore else */
if (typeof module !== 'undefined') {
R = require('ramda');
module.exports = S;
} else {
R = this.R;
this.sanctuary = S;
}
var curry = function(f) {
var arity = f.length;
var recurry = function(args) {
return function() {
var args2 = args.concat(slice_.call(arguments));
return args2.length >= arity ? f.apply(this, args2) : recurry(args2);
};
};
return recurry([]);
};
var _ = R.__;

@@ -45,9 +93,57 @@ var extend = function(Child, Parent) {

// maybe /////////////////////////////////////////////////////////////////
var filter = function(pred, m) {
return m.chain(function(x) {
return pred(x) ? m.of(x) : m.empty();
});
};
function Maybe() {
//. ### Combinator
//# K :: a -> b -> a
//.
//. The K combinator. Takes two values and returns the first. Equivalent to
//. Haskell's `const` function.
//.
//. ```javascript
//. > S.K('foo', 'bar')
//. "foo"
//. > R.map(S.K(42), R.range(0, 5))
//. [42, 42, 42, 42, 42]
//. ```
S.K = R.curry(function(x, y) {
return x;
});
//. ### Maybe type
//# 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).
//.
//. The Maybe type satisfies the [Monoid][] and [Monad][] specifications.
var Maybe = S.Maybe = function Maybe() {
throw new Error('Cannot instantiate Maybe');
}
};
// Maybe.of :: a -> m a
//# Maybe.empty :: -> Maybe a
//.
//. Returns a Nothing.
//.
//. ```javascript
//. > S.Maybe.empty()
//. Nothing()
//. ```
Maybe.empty = function() {
return new Nothing();
};
//# Maybe.of :: a -> Maybe a
//.
//. Takes a value of any type and returns a Just with the given value.
//.
//. ```javascript
//. > S.Maybe.of(42)
//. Just(42)
//. ```
Maybe.of = function(x) {

@@ -57,24 +153,200 @@ return new Just(x);

//# Maybe#ap :: Maybe (a -> b) ~> Maybe a -> Maybe b
//.
//. Takes a value of type `Maybe a` and returns a 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.Just(R.inc).ap(S.Nothing())
//. Nothing()
//.
//. > S.Just(R.inc).ap(S.Just(42))
//. Just(43)
//. ```
//# Maybe#chain :: Maybe a ~> (a -> Maybe b) -> Maybe b
//.
//. Takes a function and returns `this` if `this` is a Nothing; otherwise
//. it returns the result of applying the function to this Just's value.
//.
//. ```javascript
//. > S.Nothing().chain(S.parseFloat)
//. Nothing()
//.
//. > S.Just('xxx').chain(S.parseFloat)
//. Nothing()
//.
//. > S.Just('12.34').chain(S.parseFloat)
//. Just(12.34)
//. ```
//# Maybe#concat :: Maybe a ~> Maybe a -> Maybe a
//.
//. Returns the result of concatenating two Maybe values of the same type.
//. `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 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
//. the given Just's value.
//.
//. Otherwise, this method returns the Just.
//.
//. ```javascript
//. > 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]))
//. Just([1, 2, 3])
//.
//. > S.Just([1, 2, 3]).concat(S.Nothing())
//. Just([1, 2, 3])
//. ```
//# Maybe#empty :: Maybe a ~> Maybe a
//.
//. Returns a Nothing.
//.
//. ```javascript
//. > S.Just(42).empty()
//. Nothing()
//. ```
Maybe.prototype.empty = Maybe.empty;
//# Maybe#equals :: Maybe a ~> Maybe a -> Boolean
//.
//. Takes a Maybe and returns `true` if:
//.
//. - it is a Nothing and `this` is a Nothing; or
//.
//. - it is a Just and `this` is a Just, and their values are equal,
//. in [SameValue][] terms.
//.
//. ```javascript
//. > S.Nothing().equals(S.Nothing())
//. true
//.
//. > S.Just(42).equals(S.Just(42))
//. true
//.
//. > S.Just(42).equals(S.Just(43))
//. false
//.
//. > S.Just(42).equals(S.Nothing())
//. false
//. ```
//# Maybe#filter :: Maybe a ~> (a -> Boolean) -> Maybe a
//.
//. Takes a predicate and returns `this` if `this` is a Just whose value
//. satisfies the predicate; Nothing otherwise.
//.
//. ```javascript
//. > S.Just(42).filter(function(n) { return n % 2 === 0; })
//. Just(42)
//.
//. > S.Just(43).filter(function(n) { return n % 2 === 0; })
//. Nothing()
//. ```
Maybe.prototype.filter = function(pred) {
return filter(pred, this);
};
//# 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.
//.
//. ```javascript
//. > S.Nothing().map(R.inc)
//. Nothing()
//.
//. > S.Just(42).map(R.inc)
//. Just(43)
//. ```
//# Maybe#of :: Maybe a ~> b -> Maybe b
//.
//. Takes a value of any type and returns a Just with the given value.
//.
//. ```javascript
//. > S.Nothing().of(42)
//. Just(42)
//. ```
Maybe.prototype.of = Maybe.of;
//# Maybe#toBoolean :: Maybe a ~> Boolean
//.
//. Returns `false` if `this` is a Nothing; `true` if `this` is a Just.
//.
//. ```javascript
//. > S.Nothing().toBoolean()
//. false
//.
//. > S.Just(42).toBoolean()
//. true
//. ```
//# Maybe#toString :: Maybe a ~> String
//.
//. Returns the string representation of the Maybe.
//.
//. ```javascript
//. > S.Nothing().toString()
//. "Nothing()"
//.
//. > S.Just([1, 2, 3]).toString()
//. "Just([1, 2, 3])"
//. ```
//# Maybe#type :: Type
//.
//. A reference to the Maybe type. Useful for determining whether two
//. values such as `S.Nothing()` and `S.Just(42)` are of the same type.
Maybe.prototype.type = Maybe;
function Nothing() {
//# Nothing :: -> Maybe a
//.
//. Returns a Nothing. Though this is a constructor function the `new`
//. keyword needn't be used.
//.
//. ```javascript
//. > S.Nothing()
//. Nothing()
//. ```
var Nothing = S.Nothing = function Nothing() {
if (!(this instanceof Nothing)) {
return new Nothing();
}
}
};
extend(Nothing, Maybe);
// Nothing#ap :: m a -> m b
Nothing.prototype.ap = function(x) { // jshint ignore:line
// Nothing#ap :: Maybe (a -> b) ~> Maybe a -> Maybe b
Nothing.prototype.ap = function(x) {
return this;
};
// Nothing#chain :: (a -> m b) -> m b
Nothing.prototype.chain = function(f) { // jshint ignore:line
// Nothing#chain :: Maybe a ~> (a -> Maybe b) -> Maybe b
Nothing.prototype.chain = function(f) {
return this;
};
// Nothing#equals :: Maybe a -> Boolean
// Nothing#concat :: Maybe a ~> Maybe a -> Maybe a
Nothing.prototype.concat = function(maybe) {
return maybe;
};
// Nothing#equals :: Maybe a ~> Maybe a -> Boolean
Nothing.prototype.equals = function(maybe) {

@@ -84,13 +356,28 @@ return maybe instanceof Nothing;

// Nothing#or :: Maybe a -> Maybe a
Nothing.prototype.or = function(maybe) {
return maybe;
// Nothing#map :: Maybe a ~> (a -> b) -> Maybe b
Nothing.prototype.map = function(f) {
return this;
};
// Nothing#map :: (a -> b) -> Maybe b
Nothing.prototype.map = function(f) { // jshint ignore:line
return this;
// Nothing#toBoolean :: Maybe a ~> Boolean
Nothing.prototype.toBoolean = function() {
return false;
};
function Just(value) {
// Nothing#toString :: Maybe a ~> String
Nothing.prototype.toString = function() {
return 'Nothing()';
};
//# Just :: a -> Maybe a
//.
//. Takes a value of any type and returns a Just with the given value.
//. Though this is a constructor function the `new` keyword needn't be
//. used.
//.
//. ```javascript
//. > S.Just(42)
//. Just(42)
//. ```
var Just = S.Just = function Just(value) {
if (!(this instanceof Just)) {

@@ -101,6 +388,6 @@ return new Just(value);

}
}
};
extend(Just, Maybe);
// Just#ap :: m a -> m b
// Just#ap :: Maybe (a -> b) ~> Maybe a -> Maybe b
Just.prototype.ap = function(x) {

@@ -110,3 +397,3 @@ return x.map(this.value);

// Just#chain :: (a -> m b) -> m b
// Just#chain :: Maybe a ~> (a -> Maybe b) -> Maybe b
Just.prototype.chain = function(f) {

@@ -116,13 +403,13 @@ return f(this.value);

// Just#equals :: Maybe a -> Boolean
Just.prototype.equals = function(maybe) {
return maybe instanceof Just && maybe.value === this.value;
// Just#concat :: Maybe a ~> Maybe a -> Maybe a
Just.prototype.concat = function(maybe) {
return maybe instanceof Just ? Just(this.value.concat(maybe.value)) : this;
};
// Just#or :: Maybe a -> Maybe a
Just.prototype.or = function(maybe) { // jshint ignore:line
return this;
// Just#equals :: Maybe a ~> Maybe a -> Boolean
Just.prototype.equals = function(maybe) {
return maybe instanceof Just && R.eqProps('value', maybe, this);
};
// Just#map :: (a -> b) -> Maybe b
// Just#map :: Maybe a ~> (a -> b) -> Maybe b
Just.prototype.map = function(f) {

@@ -132,4 +419,25 @@ return new Just(f(this.value));

// fromMaybe :: a -> Maybe a -> a
var fromMaybe = curry(function(x, maybe) {
// Just#toBoolean :: Maybe a ~> Boolean
Just.prototype.toBoolean = function() {
return true;
};
// Just#toString :: Maybe a ~> String
Just.prototype.toString = function() {
return 'Just(' + R.toString(this.value) + ')';
};
//# fromMaybe :: a -> Maybe a -> a
//.
//. Takes a default value and a Maybe, and returns the Maybe's value
//. if the Maybe is a Just; the default value otherwise.
//.
//. ```javascript
//. > S.fromMaybe(0, S.Just(42))
//. 42
//.
//. > S.fromMaybe(0, S.Nothing())
//. 0
//. ```
S.fromMaybe = R.curry(function(x, maybe) {
switch (true) {

@@ -145,10 +453,32 @@ case maybe instanceof Nothing:

// toMaybe :: a? -> Maybe a
var toMaybe = function(x) {
return x == null ? Nothing() : Just(x);
};
//# toMaybe :: a? -> Maybe a
//.
//. Takes a value and returns Nothing if the value is null or undefined;
//. Just the value otherwise.
//.
//. ```javascript
//. > S.toMaybe(null)
//. Nothing()
//.
//. > S.toMaybe(42)
//. Just(42)
//. ```
S.toMaybe = R.ifElse(R.isNil, Nothing, Just);
// encase :: (* -> a) -> (* -> Maybe a)
var encase = function(f) {
return function() {
//# encase :: (* -> a) -> (* -> Maybe a)
//.
//. Takes a function `f` which may throw and returns a curried function
//. `g` which will not throw. The result of applying `g` is determined by
//. applying `f` to the same arguments: if this succeeds, `g` returns Just
//. the result; otherwise `g` returns Nothing.
//.
//. ```javascript
//. > S.encase(eval)('1 + 1')
//. Just(2)
//.
//. > S.encase(eval)('1 +')
//. Nothing()
//. ```
var encase = S.encase = R.curry(function(f) {
return R.curryN(f.length, function() {
try {

@@ -159,14 +489,181 @@ return Just(f.apply(this, arguments));

}
};
};
});
});
// either ////////////////////////////////////////////////////////////////
//. ### Either type
function Either() {
//# Either :: Type
//.
//. The Either type represents values with two possibilities: a value of type
//. `Either a b` is either a Left whose value is of type `a` or a Right whose
//. value is of type `b`.
//.
//. The Either type satisfies the [Semigroup][] and [Monad][] specifications.
var Either = S.Either = function Either() {
throw new Error('Cannot instantiate Either');
}
};
//# Either.of :: b -> Either a b
//.
//. Takes a value of any type and returns a Right with the given value.
//.
//. ```javascript
//. > S.Either.of(42)
//. Right(42)
//. ```
Either.of = function(x) {
return new Right(x);
};
//# Either#ap :: Either a (b -> c) ~> Either a b -> Either a c
//.
//. Takes a value of type `Either a b` and returns a Left unless `this`
//. is a Right *and* the argument is a Right, in which case it returns
//. a Right whose value is the result of applying this Right's value to
//. the given Right's value.
//.
//. ```javascript
//. > S.Left('Cannot divide by zero').ap(S.Right(42))
//. Left("Cannot divide by zero")
//.
//. > S.Right(R.inc).ap(S.Left('Cannot divide by zero'))
//. Left("Cannot divide by zero")
//.
//. > S.Right(R.inc).ap(S.Right(42))
//. Right(43)
//. ```
//# Either#chain :: Either a b ~> (b -> Either a c) -> Either a c
//.
//. Takes a function and returns `this` if `this` is a Left; otherwise
//. it returns the result of applying the function to this Right's value.
//.
//. ```javascript
//. > void (sqrt = function(n) { return n < 0 ? S.Left('Cannot represent square root of negative number') : S.Right(Math.sqrt(n)); })
//. undefined
//.
//. > S.Left('Cannot divide by zero').chain(sqrt)
//. Left("Cannot divide by zero")
//.
//. > S.Right(-1).chain(sqrt)
//. Left("Cannot represent square root of negative number")
//.
//. > S.Right(25).chain(sqrt)
//. Right(5)
//. ```
//# Either#concat :: Either a b ~> Either a b -> Either a b
//.
//. Returns the result of concatenating two Either values of the same type.
//. `a` must have a [Semigroup][] (indicated by the presence of a `concat`
//. method), as must `b`.
//.
//. If `this` is a Left and the argument is a Left, this method returns a
//. Left whose value is the result of concatenating this Left's value and
//. the given Left's value.
//.
//. If `this` is a Right and the argument is a Right, this method returns a
//. Right whose value is the result of concatenating this Right's value and
//. the given Right's value.
//.
//. Otherwise, this method returns the Right.
//.
//. ```javascript
//. > S.Left('abc').concat(S.Left('def'))
//. Left("abcdef")
//.
//. > S.Right([1, 2, 3]).concat(S.Right([4, 5, 6]))
//. Right([1, 2, 3, 4, 5, 6])
//.
//. > S.Left('abc').concat(S.Right([1, 2, 3]))
//. Right([1, 2, 3])
//.
//. > S.Right([1, 2, 3]).concat(S.Left('abc'))
//. Right([1, 2, 3])
//. ```
//# Either#equals :: Either a b ~> Either a b -> Boolean
//.
//. Takes an Either and returns `true` if:
//.
//. - it is a Left and `this` is a Left, and their values are equal,
//. in [SameValue][] terms; or
//.
//. - it is a Right and `this` is a Right, and their values are equal,
//. in [SameValue][] terms.
//.
//. ```javascript
//. > S.Right(42).equals(S.Right(42))
//. true
//.
//. > S.Right(42).equals(S.Left(42))
//. false
//. ```
//# Either#map :: Either a b ~> (b -> c) -> Either a c
//.
//. Takes a function and returns `this` if `this` is a Left; otherwise it
//. returns a Right whose value is the result of applying the function to
//. this Right's value.
//.
//. ```javascript
//. > S.Left('Cannot divide by zero').map(R.inc)
//. Left("Cannot divide by zero")
//.
//. > S.Right(42).map(R.inc)
//. Right(43)
//. ```
//# Either#of :: Either a b ~> b -> Either a b
//.
//. Takes a value of any type and returns a Right with the given value.
//.
//. ```javascript
//. > S.Left('Cannot divide by zero').of(42)
//. Right(42)
//. ```
Either.prototype.of = Either.of;
//# Either#toBoolean :: Either a b ~> Boolean
//.
//. Returns `false` if `this` is a Left; `true` if `this` is a Right.
//.
//. ```javascript
//. > S.Left(42).toBoolean()
//. false
//.
//. > S.Right(42).toBoolean()
//. true
//. ```
//# Either#toString :: Either a b ~> String
//.
//. Returns the string representation of the Either.
//.
//. ```javascript
//. > S.Left('Cannot divide by zero').toString()
//. "Left(\\"Cannot divide by zero\\")"
//.
//. > S.Right([1, 2, 3]).toString()
//. "Right([1, 2, 3])"
//. ```
//# Either#type :: Type
//.
//. A reference to the Either type. Useful for determining whether two
//. values such as `S.Left('Cannot divide by zero')` and `S.Right(42)`
//. are of the same type.
Either.prototype.type = Either;
function Left(value) {
//# Left :: a -> Either a b
//.
//. Takes a value of any type and returns a Left with the given value.
//. Though this is a constructor function the `new` keyword needn't be
//. used.
//.
//. ```javascript
//. > S.Left('Cannot divide by zero')
//. Left("Cannot divide by zero")
//. ```
var Left = S.Left = function Left(value) {
if (!(this instanceof Left)) {

@@ -176,16 +673,51 @@ return new Left(value);

this.value = value;
}
};
extend(Left, Either);
// Left#equals :: Either a b -> Boolean
// Left#ap :: Either a (b -> c) ~> Either a b -> Either a c
Left.prototype.ap = function(x) {
return this;
};
// Left#chain :: Either a b ~> (b -> Either a c) -> Either a c
Left.prototype.chain = function(f) {
return this;
};
// Left#concat :: Either a b ~> Either a b -> Either a b
Left.prototype.concat = function(either) {
return R.is(Left, either) ? Left(this.value.concat(either.value)) : either;
};
// Left#equals :: Either a b ~> Either a b -> Boolean
Left.prototype.equals = function(either) {
return either instanceof Left && either.value === this.value;
return either instanceof Left && R.eqProps('value', either, this);
};
// Left#map :: (b -> c) -> Either a c
Left.prototype.map = function(f) { // jshint ignore:line
// Left#map :: Either a b ~> (b -> c) -> Either a c
Left.prototype.map = function(f) {
return this;
};
function Right(value) {
// Left#toBoolean :: Either a b ~> Boolean
Left.prototype.toBoolean = function() {
return false;
};
// Left#toString :: Either a b ~> String
Left.prototype.toString = function() {
return 'Left(' + R.toString(this.value) + ')';
};
//# Right :: b -> Either a b
//.
//. Takes a value of any type and returns a Right with the given value.
//. Though this is a constructor function the `new` keyword needn't be
//. used.
//.
//. ```javascript
//. > S.Right(42)
//. Right(42)
//. ```
var Right = S.Right = function Right(value) {
if (!(this instanceof Right)) {

@@ -195,11 +727,26 @@ return new Right(value);

this.value = value;
}
};
extend(Right, Either);
// Right#equals :: Either a b -> Boolean
// Right#ap :: Either a (b -> c) ~> Either a b -> Either a c
Right.prototype.ap = function(x) {
return x.map(this.value);
};
// Right#chain :: Either a b ~> (b -> Either a c) -> Either a c
Right.prototype.chain = function(f) {
return f(this.value);
};
// Right#concat :: Either a b ~> Either a b -> Either a b
Right.prototype.concat = function(either) {
return R.is(Right, either) ? Right(this.value.concat(either.value)) : this;
};
// Right#equals :: Either a b ~> Either a b -> Boolean
Right.prototype.equals = function(either) {
return either instanceof Right && either.value === this.value;
return either instanceof Right && R.eqProps('value', either, this);
};
// Right#map :: (b -> c) -> Either a c
// Right#map :: Either a b ~> (b -> c) -> Either a c
Right.prototype.map = function(f) {

@@ -209,4 +756,27 @@ return new Right(f(this.value));

// either :: (a -> c) -> (b -> c) -> Either a b -> c
var either = curry(function(l, r, either) {
// Right#toBoolean :: Either a b ~> Boolean
Right.prototype.toBoolean = function() {
return true;
};
// Right#toString :: Either a b ~> String
Right.prototype.toString = function() {
return 'Right(' + R.toString(this.value) + ')';
};
//# either :: (a -> c) -> (b -> c) -> Either a b -> c
//.
//. Takes two functions and an Either, and returns the result of
//. applying the first function to the Left's value, if the Either
//. is a Left, or the result of applying the second function to the
//. Right's value, if the Either is a Right.
//.
//. ```javascript
//. > S.either(R.toUpper, R.toString, S.Left('Cannot divide by zero'))
//. "CANNOT DIVIDE BY ZERO"
//.
//. > S.either(R.toUpper, R.toString, S.Right(42))
//. "42"
//. ```
S.either = R.curry(function(l, r, either) {
switch (true) {

@@ -222,21 +792,108 @@ case either instanceof Left:

// control ///////////////////////////////////////////////////////////////
//. ### Control
// or :: f a -> f a -> f a
var or = curry(function(x, y) {
if (toString_.call(x) !== toString_.call(y) || x.type !== y.type) {
var assertTypeMatch = function(x, y) {
if (R.type(x) !== R.type(y) || x.type !== y.type) {
throw new TypeError('Type mismatch');
} else if (typeof x.or === 'function') {
return x.or(y);
} else if (isArray(x)) {
return x.length > 0 ? x : y;
} else {
throw new TypeError('"or" unspecified for ' + x.constructor.name);
}
};
// toBoolean :: * -> Boolean
var toBoolean = function(x) {
if (R.is(Array, x)) return x.length > 0;
if (R.is(Boolean, x)) return x;
if (R.is(Function, x.toBoolean)) return x.toBoolean();
throw new TypeError(R.toString(x) + ' does not have a "toBoolean" method');
};
// empty :: a -> a
var empty = function(x) {
if (R.is(Array, x)) return [];
if (R.is(Boolean, x)) return false;
if (R.is(Function, x.empty)) return x.empty();
throw new TypeError(R.toString(x) + ' does not have an "empty" method');
};
//# and :: a -> a -> a
//.
//. Takes two values of the same type and returns the second value
//. if the first is "true"; the first value otherwise. An array is
//. considered "true" if its length is greater than zero. The Boolean
//. value `true` is also considered "true". Other types must provide
//. a `toBoolean` method.
//.
//. ```javascript
//. > S.and(S.Just(1), S.Just(2))
//. Just(2)
//.
//. > S.and(S.Nothing(), S.Just(3))
//. Nothing()
//. ```
S.and = R.curry(function(x, y) {
assertTypeMatch(x, y);
return toBoolean(x) ? y : x;
});
// list //////////////////////////////////////////////////////////////////
//# or :: a -> a -> a
//.
//. Takes two values of the same type and returns the first value if it
//. is "true"; the second value otherwise. An array is considered "true"
//. if its length is greater than zero. The Boolean value `true` is also
//. considered "true". Other types must provide a `toBoolean` method.
//.
//. ```javascript
//. > S.or(S.Just(1), S.Just(2))
//. Just(1)
//.
//. > S.or(S.Nothing(), S.Just(3))
//. Just(3)
//. ```
var or = S.or = R.curry(function(x, y) {
assertTypeMatch(x, y);
return toBoolean(x) ? x : y;
});
// at :: Number -> [a] -> Maybe a
var at = curry(function(n, xs) {
//# xor :: a -> a -> a
//.
//. Takes two values of the same type and returns the "true" value
//. if one value is "true" and the other is "false"; otherwise it
//. returns the type's "false" value. An array is considered "true"
//. if its length is greater than zero. The Boolean value `true` is
//. also considered "true". Other types must provide `toBoolean` and
//. `empty` methods.
//.
//. ```javascript
//. > S.xor(S.Nothing(), S.Just(1))
//. Just(1)
//.
//. > S.xor(S.Just(2), S.Just(3))
//. Nothing()
//. ```
S.xor = R.curry(function(x, y) {
assertTypeMatch(x, y);
var xBool = toBoolean(x);
var yBool = toBoolean(y);
var xEmpty = empty(x);
return xBool !== yBool ? or(x, y) : xEmpty;
});
//. ### List
//# at :: Number -> [a] -> Maybe a
//.
//. Takes an index and a list and returns Just the element of the list at
//. the index if the index is within the list's bounds; Nothing otherwise.
//. A negative index represents an offset from the length of the list.
//.
//. ```javascript
//. > S.at(2, ['a', 'b', 'c', 'd', 'e'])
//. Just("c")
//.
//. > S.at(5, ['a', 'b', 'c', 'd', 'e'])
//. Nothing()
//.
//. > S.at(-2, ['a', 'b', 'c', 'd', 'e'])
//. Just("d")
//. ```
var at = S.at = R.curry(function(n, xs) {
var len = xs.length;

@@ -247,20 +904,74 @@ var idx = n < 0 ? len + n : n;

// head :: [a] -> Maybe a
var head = at(0);
//# head :: [a] -> Maybe a
//.
//. Takes a list and returns Just the first element of the list if the
//. list contains at least one element; Nothing if the list is empty.
//.
//. ```javascript
//. > S.head([1, 2, 3])
//. Just(1)
//.
//. > S.head([])
//. Nothing()
//. ```
S.head = at(0);
// last :: [a] -> Maybe a
var last = at(-1);
//# last :: [a] -> Maybe a
//.
//. Takes a list and returns Just the last element of the list if the
//. list contains at least one element; Nothing if the list is empty.
//.
//. ```javascript
//. > S.last([1, 2, 3])
//. Just(3)
//.
//. > S.last([])
//. Nothing()
//. ```
S.last = at(-1);
// tail :: [a] -> Maybe [a]
var tail = function(xs) {
return xs.length > 0 ? Just(slice_.call(xs, 1)) : Nothing();
};
//# tail :: [a] -> Maybe [a]
//.
//. Takes a list and returns Just a list containing all but the first
//. of the list's elements if the list contains at least one element;
//. Nothing if the list is empty.
//.
//. ```javascript
//. > S.tail([1, 2, 3])
//. Just([2, 3])
//.
//. > S.tail([])
//. Nothing()
//. ```
S.tail = R.ifElse(R.isEmpty, Nothing, R.compose(Just, R.tail));
// init :: [a] -> Maybe [a]
var init = function(xs) {
return xs.length > 0 ? Just(slice_.call(xs, 0, -1)) : Nothing();
};
//# init :: [a] -> Maybe [a]
//.
//. Takes a list and returns Just a list containing all but the last
//. of the list's elements if the list contains at least one element;
//. Nothing if the list is empty.
//.
//. ```javascript
//. > S.init([1, 2, 3])
//. Just([1, 2])
//.
//. > S.init([])
//. Nothing()
//. ```
S.init = R.ifElse(R.isEmpty, Nothing, R.compose(Just, R.init));
// find :: (a -> Boolean) -> [a] -> Maybe a
var find = curry(function(pred, xs) {
//# find :: (a -> Boolean) -> [a] -> Maybe a
//.
//. Takes a predicate and a list and returns Just the leftmost element of
//. the list which satisfies the predicate; Nothing if none of the list's
//. elements satisfies the predicate.
//.
//. ```javascript
//. > S.find(function(n) { return n < 0; }, [1, -2, 3, -4, 5])
//. Just(-2)
//.
//. > S.find(function(n) { return n < 0; }, [1, 2, 3, 4, 5])
//. Nothing()
//. ```
S.find = R.curry(function(pred, xs) {
for (var idx = 0, len = xs.length; idx < len; idx += 1) {

@@ -274,25 +985,140 @@ if (pred(xs[idx])) {

// object ////////////////////////////////////////////////////////////////
var sanctifyIndexOf = function(f) {
return R.curry(R.compose(R.ifElse(R.gte(_, 0), Just, Nothing), f));
};
// get :: String -> Object -> Maybe *
var get = curry(function(key, obj) {
return hasOwnProperty_.call(obj, key) ? Just(obj[key]) : Nothing();
//# indexOf :: a -> [a] -> Maybe Number
//.
//. Takes a value of any type and a list, and returns Just the index
//. of the first occurrence of the value in the list, if applicable;
//. Nothing otherwise.
//.
//. ```javascript
//. > S.indexOf('a', ['b', 'a', 'n', 'a', 'n', 'a'])
//. Just(1)
//.
//. > S.indexOf('x', ['b', 'a', 'n', 'a', 'n', 'a'])
//. Nothing()
//. ```
S.indexOf = sanctifyIndexOf(R.indexOf);
//# lastIndexOf :: a -> [a] -> Maybe Number
//.
//. Takes a value of any type and a list, and returns Just the index
//. of the last occurrence of the value in the list, if applicable;
//. Nothing otherwise.
//.
//. ```javascript
//. > S.lastIndexOf('a', ['b', 'a', 'n', 'a', 'n', 'a'])
//. Just(5)
//.
//. > S.lastIndexOf('x', ['b', 'a', 'n', 'a', 'n', 'a'])
//. Nothing()
//. ```
S.lastIndexOf = sanctifyIndexOf(R.lastIndexOf);
//# pluck :: String -> [{String: *}] -> [Maybe *]
//.
//. Takes a list of objects and plucks the value of the specified key
//. for each object in the list. Returns the value wrapped in a Just
//. if an object has the key and a Nothing if it does not.
//.
//. ```javascript
//. > S.pluck('a', [{a: 1, b: 2}, {a: 4, b: 5}, {b: 3, c: 7}])
//. [Just(1), Just(4), Nothing()]
//.
//. > S.pluck('x', [{x: 1}, {x: 2}, {x: undefined}])
//. [Just(1), Just(2), Just(undefined)]
//. ```
S.pluck = R.curry(function(key, xs) {
return R.map(get(key), xs);
});
// parse /////////////////////////////////////////////////////////////////
//. ### Object
// parseDate :: String -> Maybe Date
var parseDate = function(s) {
//# get :: String -> Object -> Maybe *
//.
//. Takes a property name and an object and returns Just the value of
//. the specified property of the object if the object has such an own
//. property; Nothing otherwise.
//.
//. ```javascript
//. > S.get('x', {x: 1, y: 2})
//. Just(1)
//.
//. > S.get('toString', {x: 1, y: 2})
//. Nothing()
//. ```
var get = S.get = R.ifElse(R.has, R.compose(Just, R.prop), Nothing);
//# gets :: [String] -> Object -> Maybe *
//.
//. Takes a list of property names and an object and returns Just the
//. value at the path specified by the list of property names if such
//. a path exists; Nothing otherwise.
//.
//. ```javascript
//. > S.gets(['a', 'b', 'c'], {a: {b: {c: 42}}})
//. Just(42)
//.
//. > S.gets(['a', 'b', 'c'], {})
//. Nothing()
//. ```
S.gets = R.curry(function(keys, obj) {
return R.reduce(function(acc, key) {
return R.chain(get(key), acc);
}, Just(obj), keys);
});
//. ### Parse
//# parseDate :: String -> Maybe Date
//.
//. Takes a string and returns Just the date represented by the string
//. if it does in fact represent a date; Nothing otherwise.
//.
//. ```javascript
//. > S.parseDate('2011-01-19T17:40:00Z')
//. Just(new Date("2011-01-19T17:40:00.000Z"))
//.
//. > S.parseDate('today')
//. Nothing()
//. ```
S.parseDate = R.curry(function(s) {
var d = new Date(s);
return d.valueOf() === d.valueOf() ? Just(d) : Nothing();
};
});
// parseFloat_ :: String -> Maybe Number
var parseFloat_ = function(s) {
//# parseFloat :: String -> Maybe Number
//.
//. Takes a string and returns Just the number represented by the string
//. if it does in fact represent a number; Nothing otherwise.
//.
//. ```javascript
//. > S.parseFloat('-123.45')
//. Just(-123.45)
//.
//. > S.parseFloat('foo.bar')
//. Nothing()
//. ```
S.parseFloat = R.curry(function(s) {
var n = parseFloat(s);
return n === n ? Just(n) : Nothing();
};
});
// parseInt_ :: Number -> String -> Maybe Number
var parseInt_ = curry(function(radix, s) {
//# parseInt :: Number -> String -> Maybe Number
//.
//. Takes a radix (an integer between 2 and 36 inclusive) and a string,
//. and returns Just the number represented by the string if it does in
//. fact represent a number in the base specified by the radix; Nothing
//. otherwise.
//.
//. ```javascript
//. > S.parseInt(16, '0xFF')
//. Just(255)
//.
//. > S.parseInt(16, '0xGG')
//. Nothing()
//. ```
S.parseInt = R.curry(function(radix, s) {
var n = parseInt(s, radix);

@@ -302,43 +1128,44 @@ return n === n ? Just(n) : Nothing();

// parseJson :: String -> Maybe *
var parseJson = encase(JSON.parse);
//# parseJson :: String -> Maybe *
//.
//. Takes a string which may or may not be valid JSON, and returns Just
//. the result of applying `JSON.parse` to the string if valid; Nothing
//. otherwise.
//.
//. ```javascript
//. > S.parseJson('["foo","bar","baz"]')
//. Just(["foo", "bar", "baz"])
//.
//. > S.parseJson('[')
//. Nothing()
//. ```
S.parseJson = encase(function(s) {
return JSON.parse(s);
});
// exports ///////////////////////////////////////////////////////////////
//. ### RegExp
var sanctuary = {
Either: Either,
Just: Just,
Left: Left,
Maybe: Maybe,
Nothing: Nothing,
Right: Right,
at: at,
either: either,
encase: encase,
find: find,
get: get,
head: head,
init: init,
fromMaybe: fromMaybe,
last: last,
or: or,
parseDate: parseDate,
parseFloat: parseFloat_,
parseInt: parseInt_,
parseJson: parseJson,
tail: tail,
toMaybe: toMaybe,
};
//# match :: RegExp -> String -> Maybe [Maybe String]
//.
//. Takes a pattern and a string, and returns Just a list of matches
//. if the pattern matches the string; Nothing otherwise. Each match
//. has type `Maybe String`, where a Nothing represents an unmatched
//. optional capturing group.
//.
//. ```javascript
//. > S.match(/(good)?bye/, 'goodbye')
//. Just([Just("goodbye"), Just("good")])
//.
//. > S.match(/(good)?bye/, 'bye')
//. Just([Just("bye"), Nothing()])
//. ```
S.match = R.curry(R.compose(R.map(R.map(S.toMaybe)), S.toMaybe, R.match));
/* global define, window */
}.call(this));
/* istanbul ignore else */
if (typeof module !== 'undefined') {
module.exports = sanctuary;
} else if (typeof define === 'function' && define.amd) {
define(sanctuary);
} else {
window.sanctuary = sanctuary;
}
}());
//. [Monad]: https://github.com/fantasyland/fantasy-land#monad
//. [Monoid]: https://github.com/fantasyland/fantasy-land#monoid
//. [R.map]: http://ramdajs.com/docs/#map
//. [Ramda]: http://ramdajs.com/
//. [SameValue]: http://ecma-international.org/ecma-262/5.1/#sec-9.12
//. [Semigroup]: https://github.com/fantasyland/fantasy-land#semigroup

7

package.json
{
"name": "sanctuary",
"version": "0.4.0",
"version": "0.5.0",
"description": "Refuge from unsafe JavaScript",

@@ -10,3 +10,5 @@ "license": "MIT",

},
"dependencies": {},
"dependencies": {
"ramda": "0.14.x"
},
"devDependencies": {

@@ -17,2 +19,3 @@ "istanbul": "0.3.x",

"mocha": "2.x.x",
"transcribe": "0.3.x",
"xyz": "0.5.x"

@@ -19,0 +22,0 @@ },

# Sanctuary
Sanctuary is small functional programming library inspired by Haskell and
PureScript. Sanctuary makes it possible to write safe code without null checks.
Sanctuary is a small functional programming library inspired by Haskell
and PureScript. It depends on and works nicely with [Ramda][]. Sanctuary
makes it possible to write safe code without null checks.
In JavaScript it's trivial to introduce a possible run-time type error:
words[0].toUpperCase()
If `words` is `[]` we'll get a familiar error at run-time:
TypeError: Cannot read property 'toUpperCase' of undefined
Sanctuary gives us a fighting chance of avoiding such errors. We might
write:
R.map(R.toUpper, S.head(words))
## Types
Sanctuary uses Haskell-like type signatures to describe the types of
values, including functions. `'foo'`, for example, has type `String`;
`[1, 2, 3]` has type `[Number]`. The arrow (`->`) is used to express a
function's type. `Math.abs`, for example, has type `Number -> Number`.
That is, it takes an argument of type `Number` and returns a value of
type `Number`.
[`R.map`][R.map] has type `(a -> b) -> [a] -> [b]`. That is, it takes
an argument of type `a -> b` and returns a value of type `[a] -> [b]`.
`a` and `b` are type variables: applying `R.map` to a value of type
`String -> Number` will give a value of type `[String] -> [Number]`.
Sanctuary embraces types. JavaScript doesn't support algebraic data types,
but these can be simulated by providing a group of constructor functions
whose prototypes provide the same set of methods. A value of the Maybe
type, for example, is created via the Nothing constructor or the Just
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,
the `map` method takes an implicit argument `x` in addition to the explicit
argument `y`. The type of the value upon which a method is invoked appears
at the beginning of the signature, separated from the arguments and return
value by a squiggly arrow (`~>`). The type of the `map` method of the Maybe
type is written `Maybe a ~> (a -> b) -> Maybe b`. One could read this as:
_When the `map` method is invoked on a value of type `Maybe a`
(for any type `a`) with an argument of type `a -> b` (for any type `b`),
it returns a value of type `Maybe b`._
## API
### Combinator
<h4 name="K"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L99">K :: a -> b -> a</a></code></h4>
The K combinator. Takes two values and returns the first. Equivalent to
Haskell's `const` function.
```javascript
words[0].toUpperCase()
> S.K('foo', 'bar')
"foo"
> R.map(S.K(42), R.range(0, 5))
[42, 42, 42, 42, 42]
```
If `words` is `['foo', 'bar', 'baz']` this expression will evaluate to `'FOO'`.
But what if `words` is `[]`?
### Maybe type
Sanctuary is stricter in its types than most JavaScript libraries. Its `head`
function, for example, has type `a -> Maybe a` which means it never returns
null or undefined. This forces one to consider the empty case.
<h4 name="Maybe"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L116">Maybe :: Type</a></code></h4>
`S.head(words)` evaluates to a value of type `Maybe String`. One may derive
from it a value of type `String` by applying `S.fromMaybe`. The `toUpperCase`
method can then be invoked safely:
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).
The Maybe type satisfies the [Monoid][] and [Monad][] specifications.
<h4 name="Maybe.empty"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L126">Maybe.empty :: -> Maybe a</a></code></h4>
Returns a Nothing.
```javascript
// :: String
S.fromMaybe('', S.head(words)).toUpperCase()
> S.Maybe.empty()
Nothing()
```
Without Sanctuary, one might have written:
<h4 name="Maybe.of"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L138">Maybe.of :: a -> Maybe a</a></code></h4>
Takes a value of any type and returns a Just with the given value.
```javascript
// :: String
(words.length > 0 ? words[0] : '').toUpperCase()
> S.Maybe.of(42)
Just(42)
```
Maybe is a functor, so one can use its `map` method to produce another Maybe:
<h4 name="Maybe.prototype.ap"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L150">Maybe#ap :: Maybe (a -> b) ~> Maybe a -> Maybe b</a></code></h4>
Takes a value of type `Maybe a` and returns a 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
// :: Maybe String
S.head(words).map(function(word) { return word.toUpperCase(); })
> S.Nothing().ap(S.Just(42))
Nothing()
> S.Just(R.inc).ap(S.Nothing())
Nothing()
> S.Just(R.inc).ap(S.Just(42))
Just(43)
```
This approach is even cleaner if one uses [Ramda][1]:
<h4 name="Maybe.prototype.chain"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L168">Maybe#chain :: Maybe a ~> (a -> Maybe b) -> Maybe b</a></code></h4>
Takes a function and returns `this` if `this` is a Nothing; otherwise
it returns the result of applying the function to this Just's value.
```javascript
// :: Maybe String
R.map(R.toUpper, S.head(words))
> S.Nothing().chain(S.parseFloat)
Nothing()
> S.Just('xxx').chain(S.parseFloat)
Nothing()
> S.Just('12.34').chain(S.parseFloat)
Just(12.34)
```
<h4 name="Maybe.prototype.concat"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L184">Maybe#concat :: Maybe a ~> Maybe a -> Maybe a</a></code></h4>
[1]: http://ramdajs.com/
Returns the result of concatenating two Maybe values of the same type.
`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 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
the given Just's value.
Otherwise, this method returns the Just.
```javascript
> 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]))
Just([1, 2, 3])
> S.Just([1, 2, 3]).concat(S.Nothing())
Just([1, 2, 3])
```
<h4 name="Maybe.prototype.empty"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L213">Maybe#empty :: Maybe a ~> Maybe a</a></code></h4>
Returns a Nothing.
```javascript
> S.Just(42).empty()
Nothing()
```
<h4 name="Maybe.prototype.equals"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L223">Maybe#equals :: Maybe a ~> Maybe a -> Boolean</a></code></h4>
Takes a Maybe and returns `true` if:
- it is a Nothing and `this` is a Nothing; or
- it is a Just and `this` is a Just, and their values are equal,
in [SameValue][] terms.
```javascript
> S.Nothing().equals(S.Nothing())
true
> S.Just(42).equals(S.Just(42))
true
> S.Just(42).equals(S.Just(43))
false
> S.Just(42).equals(S.Nothing())
false
```
<h4 name="Maybe.prototype.filter"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L246">Maybe#filter :: Maybe a ~> (a -> Boolean) -> Maybe a</a></code></h4>
Takes a predicate and returns `this` if `this` is a Just whose value
satisfies the predicate; Nothing otherwise.
```javascript
> S.Just(42).filter(function(n) { return n % 2 === 0; })
Just(42)
> S.Just(43).filter(function(n) { return n % 2 === 0; })
Nothing()
```
<h4 name="Maybe.prototype.map"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L262">Maybe#map :: Maybe a ~> (a -> b) -> Maybe b</a></code></h4>
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.
```javascript
> S.Nothing().map(R.inc)
Nothing()
> S.Just(42).map(R.inc)
Just(43)
```
<h4 name="Maybe.prototype.of"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L276">Maybe#of :: Maybe a ~> b -> Maybe b</a></code></h4>
Takes a value of any type and returns a Just with the given value.
```javascript
> S.Nothing().of(42)
Just(42)
```
<h4 name="Maybe.prototype.toBoolean"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L286">Maybe#toBoolean :: Maybe a ~> Boolean</a></code></h4>
Returns `false` if `this` is a Nothing; `true` if `this` is a Just.
```javascript
> S.Nothing().toBoolean()
false
> S.Just(42).toBoolean()
true
```
<h4 name="Maybe.prototype.toString"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L298">Maybe#toString :: Maybe a ~> String</a></code></h4>
Returns the string representation of the Maybe.
```javascript
> S.Nothing().toString()
"Nothing()"
> S.Just([1, 2, 3]).toString()
"Just([1, 2, 3])"
```
<h4 name="Maybe.prototype.type"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L310">Maybe#type :: Type</a></code></h4>
A reference to the Maybe type. Useful for determining whether two
values such as `S.Nothing()` and `S.Just(42)` are of the same type.
<h4 name="Nothing"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L316">Nothing :: -> Maybe a</a></code></h4>
Returns a Nothing. Though this is a constructor function the `new`
keyword needn't be used.
```javascript
> S.Nothing()
Nothing()
```
<h4 name="Just"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L367">Just :: a -> Maybe a</a></code></h4>
Takes a value of any type and returns a Just with the given value.
Though this is a constructor function the `new` keyword needn't be
used.
```javascript
> S.Just(42)
Just(42)
```
<h4 name="fromMaybe"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L421">fromMaybe :: a -> Maybe a -> a</a></code></h4>
Takes a default value and a Maybe, and returns the Maybe's value
if the Maybe is a Just; the default value otherwise.
```javascript
> S.fromMaybe(0, S.Just(42))
42
> S.fromMaybe(0, S.Nothing())
0
```
<h4 name="toMaybe"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L444">toMaybe :: a? -> Maybe a</a></code></h4>
Takes a value and returns Nothing if the value is null or undefined;
Just the value otherwise.
```javascript
> S.toMaybe(null)
Nothing()
> S.toMaybe(42)
Just(42)
```
<h4 name="encase"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L458">encase :: (* -> a) -> (* -> Maybe a)</a></code></h4>
Takes a function `f` which may throw and returns a curried function
`g` which will not throw. The result of applying `g` is determined by
applying `f` to the same arguments: if this succeeds, `g` returns Just
the result; otherwise `g` returns Nothing.
```javascript
> S.encase(eval)('1 + 1')
Just(2)
> S.encase(eval)('1 +')
Nothing()
```
### Either type
<h4 name="Either"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L484">Either :: Type</a></code></h4>
The Either type represents values with two possibilities: a value of type
`Either a b` is either a Left whose value is of type `a` or a Right whose
value is of type `b`.
The Either type satisfies the [Semigroup][] and [Monad][] specifications.
<h4 name="Either.of"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L495">Either.of :: b -> Either a b</a></code></h4>
Takes a value of any type and returns a Right with the given value.
```javascript
> S.Either.of(42)
Right(42)
```
<h4 name="Either.prototype.ap"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L507">Either#ap :: Either a (b -> c) ~> Either a b -> Either a c</a></code></h4>
Takes a value of type `Either a b` and returns a Left unless `this`
is a Right *and* the argument is a Right, in which case it returns
a Right whose value is the result of applying this Right's value to
the given Right's value.
```javascript
> S.Left('Cannot divide by zero').ap(S.Right(42))
Left("Cannot divide by zero")
> S.Right(R.inc).ap(S.Left('Cannot divide by zero'))
Left("Cannot divide by zero")
> S.Right(R.inc).ap(S.Right(42))
Right(43)
```
<h4 name="Either.prototype.chain"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L525">Either#chain :: Either a b ~> (b -> Either a c) -> Either a c</a></code></h4>
Takes a function and returns `this` if `this` is a Left; otherwise
it returns the result of applying the function to this Right's value.
```javascript
> void (sqrt = function(n) { return n < 0 ? S.Left('Cannot represent square root of negative number') : S.Right(Math.sqrt(n)); })
undefined
> S.Left('Cannot divide by zero').chain(sqrt)
Left("Cannot divide by zero")
> S.Right(-1).chain(sqrt)
Left("Cannot represent square root of negative number")
> S.Right(25).chain(sqrt)
Right(5)
```
<h4 name="Either.prototype.concat"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L544">Either#concat :: Either a b ~> Either a b -> Either a b</a></code></h4>
Returns the result of concatenating two Either values of the same type.
`a` must have a [Semigroup][] (indicated by the presence of a `concat`
method), as must `b`.
If `this` is a Left and the argument is a Left, this method returns a
Left whose value is the result of concatenating this Left's value and
the given Left's value.
If `this` is a Right and the argument is a Right, this method returns a
Right whose value is the result of concatenating this Right's value and
the given Right's value.
Otherwise, this method returns the Right.
```javascript
> S.Left('abc').concat(S.Left('def'))
Left("abcdef")
> S.Right([1, 2, 3]).concat(S.Right([4, 5, 6]))
Right([1, 2, 3, 4, 5, 6])
> S.Left('abc').concat(S.Right([1, 2, 3]))
Right([1, 2, 3])
> S.Right([1, 2, 3]).concat(S.Left('abc'))
Right([1, 2, 3])
```
<h4 name="Either.prototype.equals"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L574">Either#equals :: Either a b ~> Either a b -> Boolean</a></code></h4>
Takes an Either and returns `true` if:
- it is a Left and `this` is a Left, and their values are equal,
in [SameValue][] terms; or
- it is a Right and `this` is a Right, and their values are equal,
in [SameValue][] terms.
```javascript
> S.Right(42).equals(S.Right(42))
true
> S.Right(42).equals(S.Left(42))
false
```
<h4 name="Either.prototype.map"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L592">Either#map :: Either a b ~> (b -> c) -> Either a c</a></code></h4>
Takes a function and returns `this` if `this` is a Left; otherwise it
returns a Right whose value is the result of applying the function to
this Right's value.
```javascript
> S.Left('Cannot divide by zero').map(R.inc)
Left("Cannot divide by zero")
> S.Right(42).map(R.inc)
Right(43)
```
<h4 name="Either.prototype.of"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L606">Either#of :: Either a b ~> b -> Either a b</a></code></h4>
Takes a value of any type and returns a Right with the given value.
```javascript
> S.Left('Cannot divide by zero').of(42)
Right(42)
```
<h4 name="Either.prototype.toBoolean"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L616">Either#toBoolean :: Either a b ~> Boolean</a></code></h4>
Returns `false` if `this` is a Left; `true` if `this` is a Right.
```javascript
> S.Left(42).toBoolean()
false
> S.Right(42).toBoolean()
true
```
<h4 name="Either.prototype.toString"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L628">Either#toString :: Either a b ~> String</a></code></h4>
Returns the string representation of the Either.
```javascript
> S.Left('Cannot divide by zero').toString()
"Left(\\"Cannot divide by zero\\")"
> S.Right([1, 2, 3]).toString()
"Right([1, 2, 3])"
```
<h4 name="Either.prototype.type"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L640">Either#type :: Type</a></code></h4>
A reference to the Either type. Useful for determining whether two
values such as `S.Left('Cannot divide by zero')` and `S.Right(42)`
are of the same type.
<h4 name="Left"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L647">Left :: a -> Either a b</a></code></h4>
Takes a value of any type and returns a Left with the given value.
Though this is a constructor function the `new` keyword needn't be
used.
```javascript
> S.Left('Cannot divide by zero')
Left("Cannot divide by zero")
```
<h4 name="Right"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L700">Right :: b -> Either a b</a></code></h4>
Takes a value of any type and returns a Right with the given value.
Though this is a constructor function the `new` keyword needn't be
used.
```javascript
> S.Right(42)
Right(42)
```
<h4 name="either"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L753">either :: (a -> c) -> (b -> c) -> Either a b -> c</a></code></h4>
Takes two functions and an Either, and returns the result of
applying the first function to the Left's value, if the Either
is a Left, or the result of applying the second function to the
Right's value, if the Either is a Right.
```javascript
> S.either(R.toUpper, R.toString, S.Left('Cannot divide by zero'))
"CANNOT DIVIDE BY ZERO"
> S.either(R.toUpper, R.toString, S.Right(42))
"42"
```
### Control
<h4 name="and"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L802">and :: a -> a -> a</a></code></h4>
Takes two values of the same type and returns the second value
if the first is "true"; the first value otherwise. An array is
considered "true" if its length is greater than zero. The Boolean
value `true` is also considered "true". Other types must provide
a `toBoolean` method.
```javascript
> S.and(S.Just(1), S.Just(2))
Just(2)
> S.and(S.Nothing(), S.Just(3))
Nothing()
```
<h4 name="or"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L822">or :: a -> a -> a</a></code></h4>
Takes two values of the same type and returns the first value if it
is "true"; the second value otherwise. An array is considered "true"
if its length is greater than zero. The Boolean value `true` is also
considered "true". Other types must provide a `toBoolean` method.
```javascript
> S.or(S.Just(1), S.Just(2))
Just(1)
> S.or(S.Nothing(), S.Just(3))
Just(3)
```
<h4 name="xor"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L841">xor :: a -> a -> a</a></code></h4>
Takes two values of the same type and returns the "true" value
if one value is "true" and the other is "false"; otherwise it
returns the type's "false" value. An array is considered "true"
if its length is greater than zero. The Boolean value `true` is
also considered "true". Other types must provide `toBoolean` and
`empty` methods.
```javascript
> S.xor(S.Nothing(), S.Just(1))
Just(1)
> S.xor(S.Just(2), S.Just(3))
Nothing()
```
### List
<h4 name="at"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L867">at :: Number -> [a] -> Maybe a</a></code></h4>
Takes an index and a list and returns Just the element of the list at
the index if the index is within the list's bounds; Nothing otherwise.
A negative index represents an offset from the length of the list.
```javascript
> S.at(2, ['a', 'b', 'c', 'd', 'e'])
Just("c")
> S.at(5, ['a', 'b', 'c', 'd', 'e'])
Nothing()
> S.at(-2, ['a', 'b', 'c', 'd', 'e'])
Just("d")
```
<h4 name="head"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L889">head :: [a] -> Maybe a</a></code></h4>
Takes a list and returns Just the first element of the list if the
list contains at least one element; Nothing if the list is empty.
```javascript
> S.head([1, 2, 3])
Just(1)
> S.head([])
Nothing()
```
<h4 name="last"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L903">last :: [a] -> Maybe a</a></code></h4>
Takes a list and returns Just the last element of the list if the
list contains at least one element; Nothing if the list is empty.
```javascript
> S.last([1, 2, 3])
Just(3)
> S.last([])
Nothing()
```
<h4 name="tail"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L917">tail :: [a] -> Maybe [a]</a></code></h4>
Takes a list and returns Just a list containing all but the first
of the list's elements if the list contains at least one element;
Nothing if the list is empty.
```javascript
> S.tail([1, 2, 3])
Just([2, 3])
> S.tail([])
Nothing()
```
<h4 name="init"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L932">init :: [a] -> Maybe [a]</a></code></h4>
Takes a list and returns Just a list containing all but the last
of the list's elements if the list contains at least one element;
Nothing if the list is empty.
```javascript
> S.init([1, 2, 3])
Just([1, 2])
> S.init([])
Nothing()
```
<h4 name="find"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L947">find :: (a -> Boolean) -> [a] -> Maybe a</a></code></h4>
Takes a predicate and a list and returns Just the leftmost element of
the list which satisfies the predicate; Nothing if none of the list's
elements satisfies the predicate.
```javascript
> S.find(function(n) { return n < 0; }, [1, -2, 3, -4, 5])
Just(-2)
> S.find(function(n) { return n < 0; }, [1, 2, 3, 4, 5])
Nothing()
```
<h4 name="indexOf"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L973">indexOf :: a -> [a] -> Maybe Number</a></code></h4>
Takes a value of any type and a list, and returns Just the index
of the first occurrence of the value in the list, if applicable;
Nothing otherwise.
```javascript
> S.indexOf('a', ['b', 'a', 'n', 'a', 'n', 'a'])
Just(1)
> S.indexOf('x', ['b', 'a', 'n', 'a', 'n', 'a'])
Nothing()
```
<h4 name="lastIndexOf"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L988">lastIndexOf :: a -> [a] -> Maybe Number</a></code></h4>
Takes a value of any type and a list, and returns Just the index
of the last occurrence of the value in the list, if applicable;
Nothing otherwise.
```javascript
> S.lastIndexOf('a', ['b', 'a', 'n', 'a', 'n', 'a'])
Just(5)
> S.lastIndexOf('x', ['b', 'a', 'n', 'a', 'n', 'a'])
Nothing()
```
<h4 name="pluck"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L1003">pluck :: String -> [{String: *}] -> [Maybe *]</a></code></h4>
Takes a list of objects and plucks the value of the specified key
for each object in the list. Returns the value wrapped in a Just
if an object has the key and a Nothing if it does not.
```javascript
> S.pluck('a', [{a: 1, b: 2}, {a: 4, b: 5}, {b: 3, c: 7}])
[Just(1), Just(4), Nothing()]
> S.pluck('x', [{x: 1}, {x: 2}, {x: undefined}])
[Just(1), Just(2), Just(undefined)]
```
### Object
<h4 name="get"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L1022">get :: String -> Object -> Maybe *</a></code></h4>
Takes a property name and an object and returns Just the value of
the specified property of the object if the object has such an own
property; Nothing otherwise.
```javascript
> S.get('x', {x: 1, y: 2})
Just(1)
> S.get('toString', {x: 1, y: 2})
Nothing()
```
<h4 name="gets"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L1037">gets :: [String] -> Object -> Maybe *</a></code></h4>
Takes a list of property names and an object and returns Just the
value at the path specified by the list of property names if such
a path exists; Nothing otherwise.
```javascript
> S.gets(['a', 'b', 'c'], {a: {b: {c: 42}}})
Just(42)
> S.gets(['a', 'b', 'c'], {})
Nothing()
```
### Parse
<h4 name="parseDate"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L1058">parseDate :: String -> Maybe Date</a></code></h4>
Takes a string and returns Just the date represented by the string
if it does in fact represent a date; Nothing otherwise.
```javascript
> S.parseDate('2011-01-19T17:40:00Z')
Just(new Date("2011-01-19T17:40:00.000Z"))
> S.parseDate('today')
Nothing()
```
<h4 name="parseFloat"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L1075">parseFloat :: String -> Maybe Number</a></code></h4>
Takes a string and returns Just the number represented by the string
if it does in fact represent a number; Nothing otherwise.
```javascript
> S.parseFloat('-123.45')
Just(-123.45)
> S.parseFloat('foo.bar')
Nothing()
```
<h4 name="parseInt"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L1092">parseInt :: Number -> String -> Maybe Number</a></code></h4>
Takes a radix (an integer between 2 and 36 inclusive) and a string,
and returns Just the number represented by the string if it does in
fact represent a number in the base specified by the radix; Nothing
otherwise.
```javascript
> S.parseInt(16, '0xFF')
Just(255)
> S.parseInt(16, '0xGG')
Nothing()
```
<h4 name="parseJson"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L1111">parseJson :: String -> Maybe *</a></code></h4>
Takes a string which may or may not be valid JSON, and returns Just
the result of applying `JSON.parse` to the string if valid; Nothing
otherwise.
```javascript
> S.parseJson('["foo","bar","baz"]')
Just(["foo", "bar", "baz"])
> S.parseJson('[')
Nothing()
```
### RegExp
<h4 name="match"><code><a href="https://github.com/plaid/sanctuary/blob/v0.5.0/index.js#L1130">match :: RegExp -> String -> Maybe [Maybe String]</a></code></h4>
Takes a pattern and a string, and returns Just a list of matches
if the pattern matches the string; Nothing otherwise. Each match
has type `Maybe String`, where a Nothing represents an unmatched
optional capturing group.
```javascript
> S.match(/(good)?bye/, 'goodbye')
Just([Just("goodbye"), Just("good")])
> S.match(/(good)?bye/, 'bye')
Just([Just("bye"), Nothing()])
```
[Monad]: https://github.com/fantasyland/fantasy-land#monad
[Monoid]: https://github.com/fantasyland/fantasy-land#monoid
[R.map]: http://ramdajs.com/docs/#map
[Ramda]: http://ramdajs.com/
[SameValue]: http://ecma-international.org/ecma-262/5.1/#sec-9.12
[Semigroup]: https://github.com/fantasyland/fantasy-land#semigroup
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc