fantasy-land compliance
See original GitHub issueTyped Static-land compliance
This document outlines a strategy that promises at the very least a guarantee a library will not become incompatible with the Static-land specification and at best allows a path towards full compatibility, without clobbering users with hard to understand terminology, such as monoids, monads and functors.
Rules
A list of Static-land reserved function names, with TypeScript types, is provided at the bottom
- No type will export a function name out of the reserved list, without also sharing type and behavior
- If a function shares the type of a Static-land reserved function and has the same behavior, either an alias is made or the method receives the same name
The first rule simply means that if you have, for example, a map
method that’s not compliant with the Functor.map
, you name it transform
or select
instead. Array.map
is compliant with Functor.map
, it’s actually unusual for name collisions to happen, as Static-land is based on vanilla JavaScript.
The second rule is just to make sure that if there exists, for example, a flatMap
compliant with Chain.chain
(as in many libraries), compatibility with Static-land is ensured by either having an alias or simply naming it chain
in the first place.
Fantasy-land compliance
Each type that exports Static-land compliant functions also has non-enumerable namespaced methods on the type. For example, if a map
function exists, the type itself also has a fantasy-land/map
property, which is compliant with Fantasy-land (usually the same signature as Static-land, but with this
functioning as the type to act on. By making these non-enumerable, you only come across them if you’re looking (no pollution of the type). These act as a formal protocol for libraries such as Ramda, so they know how to handle that type.
Static-land reserved functions
For expected behavior, check the Static-land spec. These mostly do exactly what you expect them to do. Static-land never collapses though, so a list of lists is never automatically flattened, for example. Obviously, names of parameters are not important, signature is.
In these, Type is a stand-in for the type in question, generic parameters are noted as A, B, C, etc. A type can always have more generic parameters than specified, but never less.
equals(a: Type, b: Type): boolean
lte(a: Type, b: Type): boolean
concat(a: Type, b: Type): Type
empty(): Type
map<A, B>(f: (a: A) => B, ta: Type<A>): Type<B>
bimap<A, B, C, D>(fa: (a: A) => B, fc: (c: C) => D, ta: Type<A, C>): Type<B, D>
contramap<A, B>(f: (a: A) => B, tb: Type<B>): Type<A>
promap<A, B, C, D>(fa: (a: A) => B, fc: (c: C) => D, tbc: Type<B, C>): Type<A, D>
ap<A, B>(f: Type<(a: A) => B>, ta: Type<A>): Type<B>
of<A>(a: A): Type<A>
alt<A>(a: Type<A>, b: Type<A>): Type<A>
zero<A>(): Type<A>
chain<A, B>(f: (a: A) => Type<B>, ta: Type<A>): Type<B>
chainRec // Not easily typable in TypeScript
reduce<A, B>(f: (a: A, b: B) => A, a: A, tb: Type<B>): A
extend<A, B>(f: (ta: Type<A>) => B, ta: Type<A>): Type<B>
extract<A>(ta: Type<A>): A
traverse // Not easily typable in TypeScript
Progress
General
- Refactor all isEqual functions to equals
- Add namespaced fantasy methods
- Write tests for the laws in Static-land
List
- Look at unifying List with other structures #31
- Add fold primitive to internals
- Add List/of
- Add List/zero
- Add List/alt
- Add List/map #51
- Add List/filter
- Add List/ap
- Add List/reduce
- Add List/chain
- Add List/traverse
- Add List/extend
Original Post: How important is compliance to fantasy-land/static-land for this project? I’d like to use this project together with Ramda and fantasy-land libraries.
I’m willing to help out on this front
Issue Analytics
- State:
- Created 6 years ago
- Reactions:2
- Comments:26 (24 by maintainers)
Top GitHub Comments
hey @shinzui
I have a few more PRs ready for Fantasy-land support, but my job got kinda hectic in August and onwards. I’ll try to push the stuff I have and share the parts that still need to be done (I have them in a gist somewhere).
Proposal: Typed Static-land compliance
This document outlines a strategy that promises at the very least a guarantee a library will not become incompatible with the Static-land specification and at best allows a path towards full compatibility, without clobbering users with hard to understand terminology, such as monoids, monads and functors.
Rules
A list of Static-land reserved function names, with TypeScript types, is provided at the bottom
The first rule simply means that if you have, for example, a
map
method that’s not compliant with theFunctor.map
, you name ittransform
orselect
instead.Array.map
is compliant withFunctor.map
, it’s actually unusual for name collisions to happen, as Static-land is based on vanilla JavaScript. The second rule is just to make sure that if there exists, for example, aflatMap
compliant withChain.chain
(as in many libraries), compatibility with Static-land is ensured by either having an alias or simply naming itchain
in the first place.Fantasy-land compliance
Each type that exports Static-land compliant functions also has non-enumerable namespaced methods on the type. For example, if a
map
function exists, the type itself also has afantasy-land/map
property, which is compliant with Fantasy-land (usually the same signature as Static-land, but withthis
functioning as the type to act on. By making these non-enumerable, you only come across them if you’re looking (no pollution of the type). These act as a formal protocol for libraries such as Ramda, so they know how to handle that type.Static-land reserved functions
For expected behavior, check the Static-land spec. These mostly do exactly what you expect them to do. Static-land never collapses though, so a list of lists is never automatically flattened, for example. Obviously, names of parameters are not important, signature is.
In these, Type is a stand-in for the type in question, generic parameters are noted as A, B, C, etc. A type can always have more generic parameters than specified, but never less.