# Dart Functors, Applicatives, And Monads In Pictures

`/// The Maybe type encapsulates an optional value./// Using Maybe is a good way to deal with errors or /// exceptional cases without resorting to/// drastic measures such as error.abstract class Maybe<T> {}/// Represents a value of type Maybe that contains a value/// (represented as Just a).class Just<T> extends Maybe<T> { Just(this.value); final T value;}/// Represents an empty Maybe that holds nothing/// (in which case it has the value of Nothing)class Nothing<T> extends Maybe<T> {}`

# Functors

`num plus3(num x) => x + 3;Just(2).fmap(plus3); // Just 5`

# Just what is a Functor, really?

`abstract class Functor<T> { Functor<U> fmap<U>(U Function(T) f);}`
`Just(2).fmap(plus3); // Just 5`
`abstract class Maybe<T> implements Functor<T> {}class Just<T> extends Maybe<T> {  …   @override  Maybe<U> fmap<U>(U Function(T) f) => Just(f(value));}class Nothing<T> extends Maybe<T> {  @override  Maybe<U> fmap<U>(U Function(T) f) => Nothing();}`
`Nothing<num>().fmap(plus3); // Nothing`
`final post = Post.findByID(1);if (post != null) {  return post.title;} else {  return null;}`
`final getPostTitle = (Post post) => post.title;return Post.findByID(42).fmap(getPostTitle);`
`[2, 4, 6].map((x) => x + 3); // [5, 7, 9]`
`Iterable<T> map<T>(T toElement(E e)) => MappedIterable<E, T>(this, toElement);`
`fmap((x) => x + 3, (x) => x + 2);`
`typedef IntFunction = int Function(int);IntFunction fmap(IntFunction f, IntFunction g) => (x) => f(g(x));final foo = fmap((x) => x + 3, (x) => x + 2);foo(10); // 15`

# Applicatives

`abstract class Applicative<T> {  Applicative<U> apply<U>(Applicative<U Function(T)> f);}abstract class Maybe<T> implements …, Applicative<T> {}class Just<T> extends Maybe<T> { … @override Maybe<U> apply<U>(covariant Maybe<U Function(T)> f) => f.fmap((ff) => ff(value)) as Maybe<U>;}class Nothing<T> extends Maybe<T> { … @override Maybe<U> apply<U>(covariant Maybe<U Function(T)> f) => Nothing();}`
`Just(2).apply(Just((x) => x + 3)); // Just 5`
`extension ApplicativeList on List {  Iterable<U> apply<T, U>(List<U Function(T)> list) sync* {    for (final item in list) {      for (var i = 0; i < length; i++) {        yield item(this[i]);      }    }  }}`
`[1, 2, 3].apply<int, int>([ (x) => x * 2, (x) => x + 3,]); // [2, 4, 6, 4, 5, 6]`
`final curriedAddition = (num x) => (num y) => x + y;final a = Just(3).fmap(curriedAddition); // Just<(int) => int>Just(5).fmap(a); // COMPILATION ERROR//??? WHAT DOES THIS EVEN MEAN WHY IS THE FUNCTION WRAPPED IN A JUST`
`Just(5).apply(a); // Just 8`
`final curriedTimes = (int x) => (int y) => x * y;Just(5).apply(Just(3).fmap(curriedTimes)); // Just 15`

1. Get a PhD in computer science.
2. Throw it away because you don’t need it for this section!
`Maybe<num> half(num a) => a % 2 == 0 ? Just(a / 2) : Nothing();`
`Just(3).bind(half); // NothingJust(4).bind(half); // Just 2Nothing<num>().bind(half); // Nothing`
`abstract class Monad<T> { Maybe<U> bind<U>(Maybe<U> Function(T) f);}`
`abstract class Maybe<T> implements ..., Monad<T> {}class Just<T> extends Maybe<T> { … @override Maybe<U> bind<U>(covariant Maybe<U> Function(T) f) => f(value);}class Nothing<T> extends Maybe<T> { … @override Maybe<U> bind<U>(covariant Maybe<U> Function(T) f) => Nothing();}`
`Just(20).bind(half).bind(half).bind(half); // Nothing`

# Conclusion

1. A functor is a data type that implements the Functor abstract class.
2. An applicative is a data type that implements the Applicative abstract class.
3. A monad is a data type that implements the Monad abstract class.
4. A Maybe implements all three, so it is a functor, an applicative, and a monad.
• functors: you apply a function to a wrapped value using fmap
• applicatives: you apply a wrapped function to a wrapped value using apply
• monads: you apply a function that returns a wrapped value, to a wrapped value using bind.

--

--

--

## More from Oleksandr Leushchenko

Mobile developer

Love podcasts or audiobooks? Learn on the go with our new app.

Mobile developer