Even though in TypeScript the Funfix library is using abstract class to
express type classes, when implementing this type class it is recommended
that you implement it as a mixin using "implements", instead of extending
it directly with "extends". See
TypeScript: Mixins
for details and note that we already have applyMixins defined.
Implementation example:
import { HK, Functor, registerTypeClassInstance } from"funfix"class Box<T> implements HK<Box<any>, T> {
constructor(public value: T) {}
// Implements HK<Box<any>, A>, not really needed, but useful in order// to avoid type casts. Note these can and should be undefined:
readonly _funKindF: Box<any>
readonly _funKindA: T
}
// Type alias defined for readabilitytype BoxK<T> = HK<Box<any>, T>
// Actual implementationclass BoxFunctor implements Functor<Box<any>> {
map<A, B>(fa: BoxK<A>, f: (a: A) => B): Box<B> {
consta = (fa as Box<A>).valuereturnnewBox(f(a))
}
}
// RegisteringglobalFunctorinstanceforBoxregisterTypeClassInstance(Functor)(Box, new BoxFunctor())
We are using implements in order to support multiple inheritance and to
avoid inheriting any static members. In the Flow definitions (e.g.
.js.flow files) for Funfix these type classes are defined with
"interface", as they are meant to be interfaces that sometimes have
default implementations and not classes.
Credits
This type class is inspired by the equivalent in Haskell's
standard library and the implementation is inspired by the
Typelevel Cats project.
The
Functoris a type class providing themapoperation that allows lifting anffunction into the functor context and applying it.The name is short for "covariant functor".
Example:
const F = functorOf(Option) F.map(Some(1), x => x + 1) // Some(2)MUST obey the laws defined in FunctorLaws.
Implementation notes
Even though in TypeScript the Funfix library is using
abstract classto express type classes, when implementing this type class it is recommended that you implement it as a mixin using "implements", instead of extending it directly with "extends". See TypeScript: Mixins for details and note that we already haveapplyMixinsdefined.Implementation example:
import { HK, Functor, registerTypeClassInstance } from "funfix" class Box<T> implements HK<Box<any>, T> { constructor(public value: T) {} // Implements HK<Box<any>, A>, not really needed, but useful in order // to avoid type casts. Note these can and should be undefined: readonly _funKindF: Box<any> readonly _funKindA: T } // Type alias defined for readability type BoxK<T> = HK<Box<any>, T> // Actual implementation class BoxFunctor implements Functor<Box<any>> { map<A, B>(fa: BoxK<A>, f: (a: A) => B): Box<B> { const a = (fa as Box<A>).value return new Box(f(a)) } } // Registering global Functor instance for Box registerTypeClassInstance(Functor)(Box, new BoxFunctor())We are using
implementsin order to support multiple inheritance and to avoid inheriting anystaticmembers. In the Flow definitions (e.g..js.flowfiles) for Funfix these type classes are defined with "interface", as they are meant to be interfaces that sometimes have default implementations and not classes.Credits
This type class is inspired by the equivalent in Haskell's standard library and the implementation is inspired by the Typelevel Cats project.