The necessity of monads in Haskell maintains the pure functionality of the language but can test the patience of its programmers. An understanding of monads is essential if you want to work with Haskell. This tutorial offers a quick look at the structure of the [Monad](http://hackage.haskell.org/package/base-4.11.1.0/docs/Control-Monad.html)
typeclass. While you’ll need familiarity with Haskell, specifically, to understand how to tackle its Monad
typeclass, the concepts presented in this tutorial are easily transferred to other languages. We’ll also be covering the [Applicative](http://hackage.haskell.org/package/base-4.11.1.0/docs/Control-Applicative.html)
and [Functor](http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Functor.html)
typeclasses. Let’s start with the boring, technical definition. A monad is a particular typeclass that is primarily composed of 2 functions, bind
and return
. This is simple enough, right? Now let’s break down some terminology and find out why these 2 functions are so powerful and how all of this affects your real world code.
You may be a bit confused, what’s a typeclass? Think of a typeclass as an interface that defines a set of functions. You can define an instance of the typeclass for a data type. Now let’s look at these 2 functions, bind
and return
. The first, return
, takes a value and applies a data constructor to it. Then the second function, bind
, allows you to use the value in your data type in a sequential computation. Why would you use monads in your code? The simple answer is so you can do useful work such as manipulation and management of input and output and asynchronous programming. Next let’s talk about 2 other important concepts in Haskell: Applicative
and Functor
.
A data type that is an instance of the Functor
typeclass will implement fmap
. This function allows you to run an arbitrary function on the value or values in your data type. The Applicative
typeclass defines an infix operator, <*>
, which applies a value in a data type to another value in a data type. For example, applying a function to two lists since each list has an instance of Functor
. Adding instances of these typeclasses to an instance of Monad
enables you to do more with your data types. Next let’s look at some data types that are instances of Monad
and their practical operation in your every day programming life.
The first data type we’ll examine is [Maybe](http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-Maybe.html)
. Maybe
has an instance of Monad
. This data type allows you to represent a value or the lack of a value. Let’s talk about this type in terms of the 2 functions we learned about earlier. First return
wraps a value in the data constructor Just
. Just
acts like a function and when we try to bind
a value to a name or use the value somehow Just
will either give us our value or will fail
and return Nothing
. Finally, let’s look at another data type, [List](http://hackage.haskell.org/package/base-4.11.1.0/docs/Data-List.html)
. Just like Maybe
there is an instance of Monad
for List
. Along the same lines as the last implementation this return
wraps a value in the data constructor List
. Functions that operate on lists use bind
to take all the values in the list as input. This can be thought of as similar to a for loop for []
. Then the function will return a new list which is still an instance of the List
data type.
You can’t write effective Haskell without a few data types with Monad
instances. In the end calling something “a monad” makes it sound like a special entity. Rather, everything that people call a monad is really just a data type with some implementation of the Monad
typeclass. I hope this article helped further your understanding of an overcomplicated topic.