A Short Introduction to Functors

Mapping over wrapped values

function map<A, B>(A => B, Foo<A>) : Foo<B>
function mapSet<A, B>(fn: A => B, s: Set<A>) : Set<B> {
const result = new Set();
for (let item of s) {
result.add(fn(item))
}
return result;
}
function mapPromise<A, B>(fn: A => B, p: Promise<A>) : Promise<B> {
return p.then(fn);
}

A case when functors Maybe useful

type Maybe<A> = null | Just<A>;class Just<A> {
value: A;
constructor(value) {
this.value = value;
}
}
function mapMaybe<A, B>(fn: A => B, m: Maybe<A>) : Maybe<B> {
return m === null ? null : new Just(fn(m.value));
}
foo(x); // might throw a null reference errormapMaybe(foo, x); // Will never throw

The functor laws

  1. map must preserve identity. That is, for any functor f, map(x => x, f) has to be equal to f. This is called “identity” because the function which returns whatever value it was called with without changing it is often referred to as “the identity function”, or id. This function is implemented as x => x.
  2. map must preserve function composition. For any functor f, and any functions foo and bar, map(foo, map(bar, f)) must be equal to map(contents => foo(bar(contents)), f).

Composing Functors

mapFooBar<A, B>(fn: A => B, a: FooBar<A>) : FooBar<B> {
return mapFoo(x => mapBar(fn, x), a);
}

Further Resources

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store