Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the difference between a Functor and a Monad?

Tags:

There are similar questions here but they are attached to a particular programming language and I am looking for an answer on the conceptual level.

As I understand, Functors are essentially immutable containers that expose map() API which derives another functor. Which addition makes it possible to call a particular functor a monad?

As I understand, every monad is a functor but not every functor is a monad.

like image 487
Grzegorz Piwowarek Avatar asked Jul 22 '17 09:07

Grzegorz Piwowarek


People also ask

What is monad functor?

A functor is a data type that implements the Functor typeclass. An applicative is a data type that implements the Applicative typeclass. A monad is a data type that implements the Monad typeclass. A Maybe implements all three, so it is a functor, an applicative, and a monad.

What does a functor do?

In functional programming, a functor is a design pattern inspired by the definition from category theory, that allows for a generic type to apply a function inside without changing the structure of the generic type.

What is the difference between a function and a functor?

A function assigns to every element of a set X an element of a set Y. A functor assigns to every object of a category C an object of a category D and also assigns to every morphism in C a morphism in D in a way compatible with sources, targets, and composition.

What is a functor in Scala?

A Functor is a ubiquitous type class involving types that have one "hole", i.e. types which have the shape F[*] , such as Option , List and Future . (This is in contrast to a type like Int which has no hole, or Tuple2 which has two holes ( Tuple2[*,*] )).


2 Answers

Let me explain my understanding without going into category theory:

Functors and monads both provide some tool to wrapped input, returning a wrapped output.

Functor = unit + map (i.e. the tool)

where,

unit = something which takes raw input and wraps it inside a small context.

map = the tool which takes a function as input, applies it to raw value in wrapper, and returns wrapped result.

Example: Let us define a function which doubles an integer

// doubleMe :: Int a -> Int b const doubleMe = a => 2 * a; Maybe(2).map(doubleMe)  // Maybe(4) 

Monad = unit + flatMap (or bind or chain)

flatMap = the tool which flattens the map, as its name implies. It will be clear soon with the example below.

Example: Let us say we have a curried function which appends two strings only if both are not blank.

Let me define one as below:

append :: (string a,string b) -> Maybe(string c)   

Let's now see the problem with map (the tool that comes with Functor),

Maybe("a").map(append("b")) // Maybe(Maybe("ab"))   

How come there are two Maybes here?

Well, that's what map does; it applies the provided function to the wrapped value and wraps the result.

Let's break this into steps,

  1. Apply the mapped function to the wrapped value ; here the mapped function is append("b") and the wrapped value is "a", which results in Maybe("ab").

  2. Wrap the result, which returns Maybe(Maybe("ab")).

Now the value we are interested in is wrapped twice. Here comes flatMap to the rescue.

Maybe("a").flatMap(append("b")) // Maybe("ab") 

Of course, functors and monads have to follow some other laws too, but I believe this is not in the scope of what is asked.

like image 155
Shashank Dwivedi Avatar answered Oct 27 '22 05:10

Shashank Dwivedi


(Note that this will be a simplified explanation for category theory concepts)

Functor

A Functor is a function from a set of values a to another set of values: a -> b. For a programming language this could be a function that goes from String -> Integer:

function fn(text: string) : integer

Composition

Composition is when you use the value of one function as input to the value of the next: fa(fb(x)). For example:

hash(lowercase(text))

Monads

A Monad allows to compose Functors that either are not composable otherwise, compose Functors by adding extra functionality in the composition, or both.

  • An example of the first is a Monad for a Functor String -> (String, Integer)

  • An example of the second is a Monad that counts the Number of functions called on a value

A Monad includes a Functor T that is responsible for the functionality you want plus two other functions:

  • input -> T(input)
  • T(T(input)) -> T(input)

The first function allows to transform your input values to a set of values that our Monad can compose. The second function allows for the composition.

So in conclusion, every Monad is not a Functor but uses a Functor to complete it's purpose.

like image 39
Alexandros Panagiotakis Avatar answered Oct 27 '22 06:10

Alexandros Panagiotakis