Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Higher Kind Type dictionary
- interface _<A> { }
- type HKT = keyof _<any>
- type $<F extends HKT, A> = _<A>[F]
- // Functor Type Class
- interface Functor<F extends HKT> {
- map<A, B>(f: (a: A) => B, fa: $<F, A>): $<F, B>
- }
- // Datatype Tag
- function datatype(name: string) {
- return (constructor: Function) => {
- Reflect.defineMetadata('design:type', name, constructor);
- }
- }
- function kind(target: any) {
- return Reflect.getMetadata('design:type', target.constructor);
- }
- // Xstream Datatype
- @datatype('Xstream')
- class Xstream<A> {
- value: A
- constructor(v: A) {
- this.value = v
- }
- }
- // declare type of Xstream as HKT
- interface _<A> {
- "Xstream": Xstream<A>
- }
- // declare Functor instance of Xstream
- class XstreamFunctor implements Functor<"Xstream"> {
- map<A, B>(f: (v: A) => B, fa: Xstream<A>): Xstream<B> {
- return new Xstream(f(fa.value))
- }
- }
- @datatype('Ystream')
- class Ystream<T> {
- value: T
- constructor(v: T) {
- this.value = v
- }
- }
- interface _<A> {
- "Ystream": Ystream<A>
- }
- class YstreamFunctor implements Functor<"Ystream"> {
- map<A, B>(f: (v: A) => B, fa: Ystream<A>): Ystream<B> {
- return new Ystream(f(fa.value))
- }
- }
- // add instances into Functor dictionary
- namespace Functor {
- export const Xstream = new XstreamFunctor
- export const Ystream = new YstreamFunctor
- }
- type FunctorInstance = keyof typeof Functor
- // Polymorphic map function
- function map<F extends FunctorInstance, A, B>(f: (v: A) => B, fa: $<F, A>): $<F, B> {
- return (<any>Functor[fa.constructor.name as F]).map(f, fa) as $<F, B>
- }
- map<"Xstream", number, number>(a => a + 1, new Xstream(1))
- map<"Ystream", number, number>(a => a + 1, new Ystream(1))
Add Comment
Please, Sign In to add comment