fantasyland/fantasy-land
fantasyland/fantasy-land is tracked by TopGit as a frontend project, with 10.2k stars on GitHub, written primarily in JavaScript. Specification for interoperability of common algebraic structures in JavaScript
Snapshot summary built from the project's own GitHub metadata — there's no written TopGit review yet. The page will update automatically when a full review is published.
TopGit writes full reviews for the most-starred, most-requested repositories. This page is a snapshot until then — see the READ ME tab for the original README in full.
Snapshot
Top contributors
Show top contributors
Fantasy Land Specification
(aka "Algebraic JavaScript Specification")
This project specifies interoperability of common algebraic structures:
Setoid Semigroupoid Semigroup Foldable Functor Contravariant Filterable
(equals) (compose) (concat) (reduce) (map) (contramap) (filter)
| | | \ / | | | | \
| | | \ / | | | | \
| | | \ / | | | | \
| | | \ / | | | | \
| | | \ / | | | | \
Ord Category Monoid Traversable | | | | \
(lte) (id) (empty) (traverse) / | | \ \
| / | | \ \
| / / \ \ \
| Profunctor / \ Bifunctor \
| (promap) / \ (bimap) \
| / \ \
Group / \ \
(invert) Alt Apply Extend
(alt) (ap) (extend)
/ / \ \
/ / \ \
/ / \ \
/ / \ \
/ / \ \
Plus Applicative Chain Comonad
(zero) (of) (chain) (extract)
\ / \ / \
\ / \ / \
\ / \ / \
\ / \ / \
\ / \ / \
Alternative Monad ChainRec
(chainRec)
General
An algebra is a set of values, a set of operators that it is closed under and some laws it must obey.
Each Fantasy Land algebra is a separate specification. An algebra may have dependencies on other algebras which must be implemented.
Terminology
- "value" is any JavaScript value, including any which have the structures defined below.
- "equivalent" is an appropriate definition of equivalence for the given value.
The definition should ensure that the two values can be safely swapped out in a program that respects abstractions. For example:
- Two lists are equivalent if they are equivalent at all indices.
- Two plain old JavaScript objects, interpreted as dictionaries, are equivalent when they are equivalent for all keys.
- Two promises are equivalent when they yield equivalent values.
- Two functions are equivalent if they yield equivalent outputs for equivalent inputs.
Type signature notation
The type signature notation used in this document is described below:1
::"is a member of".e :: tcan be read as: "the expressioneis a member of typet".true :: Boolean- "trueis a member of typeBoolean".42 :: Integer, Number- "42is a member of theIntegerandNumbertypes".
- New types can be created via type constructors.
- Type constructors can take zero or more type arguments.
Arrayis a type constructor which takes one type argument.Array Stringis the type of all arrays of strings. Each of the following has typeArray String:[],['foo', 'bar', 'baz'].Array (Array String)is the type of all arrays of arrays of strings. Each of the following has typeArray (Array String):[],[ [], [] ],[ [], ['foo'], ['bar', 'baz'] ].
- Lowercase letters stand for type variables.
- Type variables can take any type unless they have been restricted by means of type constraints (see fat arrow below).
->(arrow) Function type constructor.->is an infix type constructor that takes two type arguments where left argument is the input type and the right argument is the output type.->'s input type can be a grouping of types to create the type of a function which accepts zero or more arguments. The syntax is:(<input-types>) -> <output-type>, where<input-types>comprises zero or more comma–space (,)-separated type representations and parens may be omitted for unary functions.String -> Array Stringis a type satisfied by functions which take aStringand return anArray String.String -> Array String -> Array Stringis a type satisfied by functions which take aStringand return a function which takes anArray Stringand returns anArray String.(String, Array String) -> Array Stringis a type satisfied by functions which take aStringand anArray Stringas arguments and return anArray String.() -> Numberis a type satisfied by functions which do not take arguments and return aNumber.
~>(squiggly arrow) Method type constructor.- When a function is a property of an Object, it is called a method. All methods have an implicit parameter type - the type of which they are a property.
a ~> a -> ais a type satisfied by methods on Objects of typeawhich take a typeaas an argument and return a value of typea.
=>(fat arrow) Expresses constraints on type variables.- In
a ~> a -> a(see squiggly arrow above),acan be of any type.Semigroup a => a ~> a -> aadds a constraint such that the typeamust now satisfy theSemigrouptypeclass. To satisfy a typeclass means to lawfully implement all functions/methods specified by that typeclass.
- In
For example:
fantasy-land/traverse :: Applicative f, Traversable t => t a ~> (TypeRep f, a -> f b) -> f (t b)
'-------------------' '--------------------------' '-' '-------------------' '-----'
' ' ' ' '
' ' - type constraints ' ' - argument types ' - return type
' '
'- method name ' - method target type
- See the Types section in Sanctuary's docs for more info. ↩
Type representatives
Certain behaviours are defined from the perspective of a member of a type.
Other behaviours do not require a member. Thus certain algebras require a
type to provide a value-level representative (with certain properties). The
Identity type, for example, could provide Id as its type representative:
Id :: TypeRep Identity.
If a type provides a type representative, each member of the type must have
a constructor property which is a reference to the type representative.
Algebras
Setoid
a['fantasy-land/equals'](a) === true(reflexivity)a['fantasy-land/equals'](b) === b['fantasy-land/equals'](a)(symmetry)- If
a['fantasy-land/equals'](b)andb['fantasy-land/equals'](c), thena['fantasy-land/equals'](c)(transitivity)
fantasy-land/equals method
fantasy-land/equals :: Setoid a => a ~> a -> Boolean
A value which has a Setoid must provide a fantasy-land/equals method. The
fantasy-land/equals method takes one argument:
a['fantasy-land/equals'](b)
-
bmust be a value of the same Setoid- If
bis not the same Setoid, behaviour offantasy-land/equalsis unspecified (returningfalseis recommended).
- If
-
fantasy-land/equalsmust return a boolean (trueorfalse).
Ord
A value that implements the Ord specification must also implement the Setoid specification.
a['fantasy-land/lte'](b)orb['fantasy-land/lte'](a)(totality)- If
a['fantasy-land/lte'](b)andb['fantasy-land/lte'](a), thena['fantasy-land/equals'](b)(antisymmetry) - If
a['fantasy-land/lte'](b)andb['fantasy-land/lte'](c), thena['fantasy-land/lte'](c)(transitivity)
fantasy-land/lte method
fantasy-land/lte :: Ord a => a ~> a -> Boolean
A value which has an Ord must provide a fantasy-land/lte method. The
fantasy-land/lte method takes one argument:
a['fantasy-land/lte'](b)
-
bmust be a value of the same Ord- If
bis not the same Ord, behaviour offantasy-land/lteis unspecified (returningfalseis recommended).
- If
-
fantasy-land/ltemust return a boolean (trueorfalse).
Semigroupoid
a['fantasy-land/compose'](b)['fantasy-land/compose'](c) === a['fantasy-land/compose'](b['fantasy-land/compose'](c))(associativity)
fantasy-land/compose method
fantasy-land/compose :: Semigroupoid c => c i j ~> c j k -> c i k
A value which has a Semigroupoid must provide a fantasy-land/compose method. The
fantasy-land/compose method takes one argument:
a['fantasy-land/compose'](b)
-
bmust be a value of the same Semigroupoid- If
bis not the same semigroupoid, behaviour offantasy-land/composeis unspecified.
- If
-
fantasy-land/composemust return a value of the same Semigroupoid.
Category
A value that implements the Category specification must also implement the Semigroupoid specification.
a['fantasy-land/compose'](C['fantasy-land/id']())is equivalent toa(right identity)C['fantasy-land/id']()['fantasy-land/compose'](a)is equivalent toa(left identity)
fantasy-land/id method
fantasy-land/id :: Category c => () -> c a a
A value which has a Category must provide a fantasy-land/id function on its
type representative:
C['fantasy-land/id']()
Given a value c, one can access its type representative via the
constructor property:
c.constructor['fantasy-land/id']()
fantasy-land/idmust return a value of the same Category
Semigroup
a['fantasy-land/concat'](b)['fantasy-land/concat'](c)is equivalent toa['fantasy-land/concat'](b['fantasy-land/concat'](c))(associativity)
fantasy-land/concat method
fantasy-land/concat :: Semigroup a => a ~> a -> a
A value which has a Semigroup must provide a fantasy-land/concat method. The
fantasy-land/concat method takes one argument:
s['fantasy-land/concat'](b)
-
bmust be a value of the same Semigroup- If
bis not the same semigroup, behaviour offantasy-land/concatis unspecified.
- If
-
fantasy-land/concatmust return a value of the same Semigroup.
Monoid
A value that implements the Monoid specification must also implement the Semigroup specification.
m['fantasy-land/concat'](M['fantasy-land/empty']())is equivalent tom(right identity)M['fantasy-land/empty']()['fantasy-land/concat'](m)is equivalent tom(left identity)
fantasy-land/empty method
fantasy-land/empty :: Monoid m => () -> m
A value which has a Monoid must provide a fantasy-land/empty function on its
type representative:
M['fantasy-land/empty']()
Given a value m, one can access its type representative via the
constructor property:
m.constructor['fantasy-land/empty']()
fantasy-land/emptymust return a value of the same Monoid
Group
A value that implements the Group specification must also implement the Monoid specification.
g['fantasy-land/concat'](g['fantasy-land/invert']())is equivalent tog.constructor['fantasy-land/empty']()(right inverse)g['fantasy-land/invert']()['fantasy-land/concat'](g)is equivalent tog.constructor['fantasy-land/empty']()(left inverse)
fantasy-land/invert method
fantasy-land/invert :: Group g => g ~> () -> g
A value which has a Group must provide a fantasy-land/invert method. The
fantasy-land/invert method takes no arguments:
g['fantasy-land/invert']()
fantasy-land/invertmust return a value of the same Group.
Filterable
v['fantasy-land/filter'](x => p(x) && q(x))is equivalent tov['fantasy-land/filter'](p)['fantasy-land/filter'](q)(distributivity)v['fantasy-land/filter'](x => true)is equivalent tov(identity)v['fantasy-land/filter'](x => false)is equivalent tow['fantasy-land/filter'](x => false)ifvandware values of the same Filterable (annihilation)
fantasy-land/filter method
fantasy-land/filter :: Filterable f => f a ~> (a -> Boolean) -> f a
A value which has a Filterable must provide a fantasy-land/filter method. The fantasy-land/filter
method takes one argument:
v['fantasy-land/filter'](p)
-
pmust be a function.- If
pis not a function, the behaviour offantasy-land/filteris unspecified. pmust return eithertrueorfalse. If it returns any other value, the behaviour offantasy-land/filteris unspecified.
- If
-
fantasy-land/filtermust return a value of the same Filterable.
Functor
u['fantasy-land/map'](a => a)is equivalent tou(identity)u['fantasy-land/map'](x => f(g(x)))is equivalent tou['fantasy-land/map'](g)['fantasy-land/map'](f)(composition)
fantasy-land/map method
fantasy-land/map :: Functor f => f a ~> (a -> b) -> f b
A value which has a Functor must provide a fantasy-land/map method. The fantasy-land/map
method takes one argument:
u['fantasy-land/map'](f)
-
fmust be a function,- If
fis not a function, the behaviour offantasy-land/mapis unspecified. fcan return any value.- No parts of
f's return value should be checked.
- If
-
fantasy-land/mapmust return a value of the same Functor
Contravariant
u['fantasy-land/contramap'](a => a)is equivalent tou(identity)u['fantasy-land/contramap'](x => f(g(x)))is equivalent tou['fantasy-land/contramap'](f)['fantasy-land/contramap'](g)(composition)
fantasy-land/contramap method
fantasy-land/contramap :: Contravariant f => f a ~> (b -> a) -> f b
A value which has a Contravariant must provide a fantasy-land/contramap method. The
fantasy-land/contramap method takes one argument:
u['fantasy-land/contramap'](f)
-
fmust be a function,- If
fis not a function, the behaviour offantasy-land/contramapis unspecified. fcan return any value.- No parts of
f's return value should be checked.
- If
-
fantasy-land/contramapmust return a value of the same Contravariant
Apply
A value that implements the Apply specification must also implement the Functor specification.
v['fantasy-land/ap'](u['fantasy-land/ap'](a['fantasy-land/map'](f => g => x => f(g(x)))))is equivalent tov['fantasy-land/ap'](u)['fantasy-land/ap'](a)(composition)
fantasy-land/ap method
fantasy-land/ap :: Apply f => f a ~> f (a -> b) -> f b
A value which has an Apply must provide a fantasy-land/ap method. The fantasy-land/ap
method takes one argument:
a['fantasy-land/ap'](b)
-
bmust be an Apply of a function- If
bdoes not represent a function, the behaviour offantasy-land/apis unspecified. bmust be same Apply asa.
- If
-
amust be an Apply of any value -
fantasy-land/apmust apply the function in Applybto the value in Applya- No parts of return value of that function should be checked.
-
The
Applyreturned byfantasy-land/apmust be the same asaandb
Applicative
A value that implements the Applicative specification must also implement the Apply specification.
v['fantasy-land/ap'](A['fantasy-land/of'](x => x))is equivalent tov(identity)A['fantasy-land/of'](x)['fantasy-land/ap'](A['fantasy-land/of'](f))is equivalent toA['fantasy-land/of'](f(x))(homomorphism)A['fantasy-land/of'](y)['fantasy-land/ap'](u)is equivalent tou['fantasy-land/ap'](A['fantasy-land/of'](f => f(y)))(interchange)
fantasy-land/of method
fantasy-land/of :: Applicative f => a -> f a
A value which has an Applicative must provide a fantasy-land/of function on its
type representative. The fantasy-land/of function takes
one argument:
F['fantasy-land/of'](a)
Given a value f, one can access its type representative via the
constructor property:
f.constructor['fantasy-land/of'](a)
-
fantasy-land/ofmust provide a value of the same Applicative- No parts of
ashould be checked
- No parts of
Alt
A value that implements the Alt specification must also implement the Functor specification.
a['fantasy-land/alt'](b)['fantasy-land/alt'](c)is equivalent toa['fantasy-land/alt'](b['fantasy-land/alt'](c))(associativity)a['fantasy-land/alt'](b)['fantasy-land/map'](f)is equivalent toa['fantasy-land/map'](f)['fantasy-land/alt'](b['fantasy-land/map'](f))(distributivity)
fantasy-land/alt method
fantasy-land/alt :: Alt f => f a ~> f a -> f a
A value which has a Alt must provide a fantasy-land/alt method. The
fantasy-land/alt method takes one argument:
a['fantasy-land/alt'](b)
-
bmust be a value of the same Alt- If
bis not the same Alt, behaviour offantasy-land/altis unspecified. aandbcan contain any value of same type.- No parts of
a's andb's containing value should be checked.
- If
-
fantasy-land/altmust return a value of the same Alt.
Plus
A value that implements the Plus specification must also implement the Alt specification.
x['fantasy-land/alt'](A['fantasy-land/zero']())is equivalent tox(right identity)A['fantasy-land/zero']()['fantasy-land/alt'](x)is equivalent tox(left identity)A['fantasy-land/zero']()['fantasy-land/map'](f)is equivalent toA['fantasy-land/zero']()(annihilation)
fantasy-land/zero method
fantasy-land/zero :: Plus f => () -> f a
A value which has a Plus must provide a fantasy-land/zero function on its
type representative:
A['fantasy-land/zero']()
Given a value x, one can access its type representative via the
constructor property:
x.constructor['fantasy-land/zero']()
fantasy-land/zeromust return a value of the same Plus
Alternative
A value that implements the Alternative specification must also implement the Applicative and Plus specifications.
x['fantasy-land/ap'](f['fantasy-land/alt'](g))is equivalent tox['fantasy-land/ap'](f)['fantasy-land/alt'](x['fantasy-land/ap'](g))(distributivity)x['fantasy-land/ap'](A['fantasy-land/zero']())is equivalent toA['fantasy-land/zero']()(annihilation)
Foldable
u['fantasy-land/reduce']is equivalent tou['fantasy-land/reduce']((acc, x) => acc.concat([x]), []).reduce
fantasy-land/reduce method
fantasy-land/reduce :: Foldable f => f a ~> ((b, a) -> b, b) -> b
A value which has a Foldable must provide a fantasy-land/reduce method. The fantasy-land/reduce
method takes two arguments:
u['fantasy-land/reduce'](f, x)
-
fmust be a binary function- if
fis not a function, the behaviour offantasy-land/reduceis unspecified. - The first argument to
fmust be the same type asx. fmust return a value of the same type asx.- No parts of
f's return value should be checked.
- if
-
xis the initial accumulator value for the reduction- No parts of
xshould be checked.
- No parts of
Traversable
A value that implements the Traversable specification must also implement the Functor and Foldable specifications.
-
t(u['fantasy-land/traverse'](F, x => x))is equivalent tou['fantasy-land/traverse'](G, t)for anytsuch thatt(a)['fantasy-land/map'](f)is equivalent tot(a['fantasy-land/map'](f))(naturality) -
u['fantasy-land/traverse'](F, F['fantasy-land/of'])is equivalent toF['fantasy-land/of'](u)for any ApplicativeF(identity) -
u['fantasy-land/traverse'](Compose, x => new Compose(x))is equivalent tonew Compose(u['fantasy-land/traverse'](F, x => x)['fantasy-land/map'](x => x['fantasy-land/traverse'](G, x => x)))forComposedefined below and any ApplicativesFandG(composition)
function Compose(c) {
this.c = c;
}
Compose['fantasy-land/of'] = function(x) {
return new Compose(F['fantasy-land/of'](G['fantasy-land/of'](x)));
};
Compose.prototype['fantasy-land/ap'] = function(f) {
return new Compose(this.c['fantasy-land/ap'](f.c['fantasy-land/map'](u => y => y['fantasy-land/ap'](u))));
};
Compose.prototype['fantasy-land/map'] = function(f) {
return new Compose(this.c['fantasy-land/map'](y => y['fantasy-land/map'](f)));
};
fantasy-land/traverse method
fantasy-land/traverse :: Applicative f, Traversable t => t a ~> (TypeRep f, a -> f b) -> f (t b)
A value which has a Traversable must provide a fantasy-land/traverse method. The fantasy-land/traverse
method takes two arguments:
u['fantasy-land/traverse'](A, f)
-
Amust be the type representative of an Applicative. -
fmust be a function which returns a value- If
fis not a function, the behaviour offantasy-land/traverseis unspecified. fmust return a value of the type represented byA.
- If
-
fantasy-land/traversemust return a value of the type represented byA.
Chain
A value that implements the Chain specification must also implement the Apply specification.
m['fantasy-land/chain'](f)['fantasy-land/chain'](g)is equivalent tom['fantasy-land/chain'](x => f(x)['fantasy-land/chain'](g))(associativity)
fantasy-land/chain method
fantasy-land/chain :: Chain m => m a ~> (a -> m b) -> m b
A value which has a Chain must provide a fantasy-land/chain method. The fantasy-land/chain
method takes one argument:
m['fantasy-land/chain'](f)
-
fmust be a function which returns a value- If
fis not a function, the behaviour offantasy-land/chainis unspecified. fmust return a value of the same Chain
- If
-
fantasy-land/chainmust return a value of the same Chain
ChainRec
A value that implements the ChainRec specification must also implement the Chain specification.
M['fantasy-land/chainRec']((next, done, v) => p(v) ? d(v)['fantasy-land/map'](done) : n(v)['fantasy-land/map'](next), i)is equivalent to(function step(v) { return p(v) ? d(v) : n(v)['fantasy-land/chain'](step); }(i))(equivalence)- Stack usage of
M['fantasy-land/chainRec'](f, i)must be at most a constant multiple of the stack usage offitself.
fantasy-land/chainRec method
fantasy-land/chainRec :: ChainRec m => ((a -> c, b -> c, a) -> m c, a) -> m b
A Type which has a ChainRec must provide a fantasy-land/chainRec function on its
type representative. The fantasy-land/chainRec function
takes two arguments:
M['fantasy-land/chainRec'](f, i)
Given a value m, one can access its type representative via the
constructor property:
m.constructor['fantasy-land/chainRec'](f, i)
fmust be a function which returns a value- If
fis not a function, the behaviour offantasy-land/chainRecis unspecified. ftakes three argumentsnext,done,valuenextis a function which takes one argument of same type asiand can return any valuedoneis a function which takes one argument and returns the same type as the return value ofnextvalueis some value of the same type asi
fmust return a value of the same ChainRec which contains a value returned from eitherdoneornext
- If
fantasy-land/chainRecmust return a value of the same ChainRec which contains a value of same type as argument ofdone
Monad
A value that implements the Monad specification must also implement the Applicative and Chain specifications.
M['fantasy-land/of'](a)['fantasy-land/chain'](f)is equivalent tof(a)(left identity)m['fantasy-land/chain'](M['fantasy-land/of'])is equivalent tom(right identity)
Extend
A value that implements the Extend specification must also implement the Functor specification.
w['fantasy-land/extend'](g)['fantasy-land/extend'](f)is equivalent tow['fantasy-land/extend'](_w => f(_w['fantasy-land/extend'](g)))
fantasy-land/extend method
fantasy-land/extend :: Extend w => w a ~> (w a -> b) -> w b
An Extend must provide a fantasy-land/extend method. The fantasy-land/extend
method takes one argument:
w['fantasy-land/extend'](f)
-
fmust be a function which returns a value- If
fis not a function, the behaviour offantasy-land/extendis unspecified. fmust return a value of typev, for some variablevcontained inw.- No parts of
f's return value should be checked.
- If
-
fantasy-land/extendmust return a value of the same Extend.
Comonad
A value that implements the Comonad specification must also implement the Extend specification.
w['fantasy-land/extend'](_w => _w['fantasy-land/extract']())is equivalent tow(left identity)w['fantasy-land/extend'](f)['fantasy-land/extract']()is equivalent tof(w)(right identity)
fantasy-land/extract method
fantasy-land/extract :: Comonad w => w a ~> () -> a
A value which has a Comonad must provide a fantasy-land/extract method on itself.
The fantasy-land/extract method takes no arguments:
w['fantasy-land/extract']()
fantasy-land/extractmust return a value of typev, for some variablevcontained inw.vmust have the same type thatfreturns infantasy-land/extend.
Bifunctor
A value that implements the Bifunctor specification must also implement the Functor specification.
p['fantasy-land/bimap'](a => a, b => b)is equivalent top(identity)p['fantasy-land/bimap'](a => f(g(a)), b => h(i(b)))is equivalent top['fantasy-land/bimap'](g, i)['fantasy-land/bimap'](f, h)(composition)
fantasy-land/bimap method
fantasy-land/bimap :: Bifunctor f => f a c ~> (a -> b, c -> d) -> f b d
A value which has a Bifunctor must provide a fantasy-land/bimap method. The fantasy-land/bimap
method takes two arguments:
c['fantasy-land/bimap'](f, g)
-
fmust be a function which returns a value- If
fis not a function, the behaviour offantasy-land/bimapis unspecified. fcan return any value.- No parts of
f's return value should be checked.
- If
-
gmust be a function which returns a value- If
gis not a function, the behaviour offantasy-land/bimapis unspecified. gcan return any value.- No parts of
g's return value should be checked.
- If
-
fantasy-land/bimapmust return a value of the same Bifunctor.
Profunctor
A value that implements the Profunctor specification must also implement the Functor specification.
p['fantasy-land/promap'](a => a, b => b)is equivalent top(identity)p['fantasy-land/promap'](a => f(g(a)), b => h(i(b)))is equivalent top['fantasy-land/promap'](f, i)['fantasy-land/promap'](g, h)(composition)
fantasy-land/promap method
fantasy-land/promap :: Profunctor p => p b c ~> (a -> b, c -> d) -> p a d
A value which has a Profunctor must provide a fantasy-land/promap method.
The fantasy-land/promap method takes two arguments:
c['fantasy-land/promap'](f, g)
-
fmust be a function which returns a value- If
fis not a function, the behaviour offantasy-land/promapis unspecified. fcan return any value.- No parts of
f's return value should be checked.
- If
-
gmust be a function which returns a value- If
gis not a function, the behaviour offantasy-land/promapis unspecified. gcan return any value.- No parts of
g's return value should be checked.
- If
-
fantasy-land/promapmust return a value of the same Profunctor
Derivations
When creating data types which satisfy multiple algebras, authors may choose to implement certain methods then derive the remaining methods. Derivations:
-
fantasy-land/equalsmay be derived fromfantasy-land/lte:function equals(other) { return this['fantasy-land/lte'](other) && other['fantasy-land/lte'](this); } -
fantasy-land/mapmay be derived fromfantasy-land/apandfantasy-land/of:function map(f) { return this['fantasy-land/ap'](this.constructor['fantasy-land/of'](f)); } -
fantasy-land/mapmay be derived fromfantasy-land/chainandfantasy-land/of:function map(f) { return this['fantasy-land/chain'](a => this.constructor['fantasy-land/of'](f(a))); } -
fantasy-land/mapmay be derived fromfantasy-land/bimap:function map(f) { return this['fantasy-land/bimap'](a => a, f); } -
fantasy-land/mapmay be derived fromfantasy-land/promap:function map(f) { return this['fantasy-land/promap'](a => a, f); } -
fantasy-land/apmay be derived fromfantasy-land/chain:function ap(m) { return m['fantasy-land/chain'](f => this['fantasy-land/map'](f)); } -
fantasy-land/reducemay be derived as follows:function reduce(f, acc) { function Const(value) { this.value = value; } Const['fantasy-land/of'] = function(_) { return new Const(acc); }; Const.prototype['fantasy-land/map'] = function(_) { return this; }; Const.prototype['fantasy-land/ap'] = function(b) { return new Const(f(b.value, this.value)); }; return this['fantasy-land/traverse'](x => new Const(x), Const['fantasy-land/of']).value; } -
fantasy-land/mapmay be derived as follows:function map(f) { function Id(value) { this.value = value; } Id['fantasy-land/of'] = function(x) { return new Id(x); }; Id.prototype['fantasy-land/map'] = function(f) { return new Id(f(this.value)); }; Id.prototype['fantasy-land/ap'] = function(b) { return new Id(this.value(b.value)); }; return this['fantasy-land/traverse'](x => Id['fantasy-land/of'](f(x)), Id['fantasy-land/of']).value; } -
fantasy-land/filtermay be derived fromfantasy-land/of,fantasy-land/chain, andfantasy-land/zero:function filter(pred) { var F = this.constructor; return this['fantasy-land/chain'](x => pred(x) ? F['fantasy-land/of'](x) : F['fantasy-land/zero']()); } -
fantasy-land/filtermay be derived fromfantasy-land/concat,fantasy-land/of,fantasy-land/zero, andfantasy-land/reduce:function filter(pred) { var F = this.constructor; return this['fantasy-land/reduce']((f, x) => pred(x) ? f['fantasy-land/concat'](F['fantasy-land/of'](x)) : f, F['fantasy-land/zero']()); }
If a data type provides a method which could be derived, its behaviour must be equivalent to that of the derivation (or derivations).
Notes
- If there's more than a single way to implement the methods and laws, the implementation should choose one and provide wrappers for other uses.
- It's discouraged to overload the specified methods. It can easily result in broken and buggy behaviour.
- It is recommended to throw an exception on unspecified behaviour.
- An
Identitycontainer which implements many of the methods is provided by sanctuary-identity.
Alternatives
There also exists Static Land Specification with exactly the same ideas as Fantasy Land but based on static methods instead of instance methods.
Related repositories
freeCodeCamp is a free, self-paced curriculum for learning to code, published as open source at freeCodeCamp/freeCodeCamp. It's a 501(c)(3) nonprofit funded by donor support, structured around six certifications in its Full-Stack Developer Curriculum, each gated by required projects instead of open-book quizzes. The repository also carries beta language certifications for developers, interview-prep resources, and the code that runs the live freecodecamp.org platform.
Vue 2, also known as Vue.js 2, is the earlier major version of the Vue JavaScript framework, hosted at vuejs/vue on GitHub under an MIT license. Per the repository's own README, Vue 2 hit End of Life on December 31, 2023, is no longer actively maintained, and the project now directs users toward vuejs/core (Vue 3) and an official migration guide, while leaving Vue 2 itself installable through CDNs, package managers, and GitHub.
Bootstrap is an open-source front-end framework maintained at twbs/bootstrap. It ships compiled and minified CSS and JavaScript for building responsive, mobile-first sites, is licensed under MIT, and the release referenced throughout the README's install instructions is v5.3.8. The project was created by Mark Otto and Jacob Thornton, and its documentation is built with Astro and hosted at getbootstrap.com.
Airbnb JavaScript Style Guide is a public reference of JavaScript coding conventions maintained in the airbnb/javascript GitHub repository, covering rules for types, references, objects, arrays, destructuring, strings, and functions, among other topics. Most guidelines cite a matching ESLint rule and show bad-versus-good code side by side, and the project also links companion guides for React and CSS-in-JavaScript.
Quick answers
How does fantasyland/fantasy-land compare to other Frontend projects?
fantasyland/fantasy-land is tracked by TopGit in the Frontend category, with 10.2k GitHub stars and written in JavaScript. Browse the Frontend topic page on TopGit to compare it against similar projects by stars and activity.
Is fantasyland/fantasy-land open source?
Yes — fantasyland/fantasy-land ships under the MIT license, which makes its source code freely readable (and, depending on license terms, forkable and reusable). Source: github.com/fantasyland/fantasy-land.
What else is in the Frontend space?
fantasyland/fantasy-land is tracked by TopGit under the Frontend category, alongside 4 GitHub-tagged topics. Trending and Topics pages list peer repositories of comparable stars and language.
What is fantasyland/fantasy-land?
fantasyland/fantasy-land (fantasyland/fantasy-land) is a JavaScript project on GitHub. From the project's own README: Specification for interoperability of common algebraic structures in JavaScript
Where do I read more about fantasyland/fantasy-land?
This TopGit page is a snapshot — the READ ME tab shows the project's own README content (links stripped, images preserved). The GitHub repository at github.com/fantasyland/fantasy-land is the definitive source.
Why is fantasyland/fantasy-land categorized under Frontend?
TopGit places fantasyland/fantasy-land in the Frontend category based on its GitHub topics and description (tagged: "fantasy-land", "functional", "javascript"). Categories are assigned from real repository metadata, not editorial guesswork.
Read full README in the tab above.
Want a second opinion on fantasy-land?
Ask an AI that can read this page — one click and you get its take on fantasy-land.