I am getting very confused with these three concepts.
Is there any simple examples to illustrate the differences between
Category, Monoid and Monad ?
It would be very helpful if there is a illustration of these abstract concepts.
This probably isn't the answer you're looking for, but here you go anyways:
A really crooked way of looking at monads & co.
One way of looking at abstract concepts like these is to link them with basic concepts, such as ordinary list processing operations. Then, you could say that,
A category generalizes the (.) operation.
A monoid generalizes the (++) operation.
A functor generalises the map operation.
An applicative functor generalizes the zip (or zipWith) operation.
A monad generalizes the concat operation.
A Category
A category consists of a set (or a class) of objects and bunch of arrows that each connect two of the objects. In addition, for each object, there should be an identity arrow connecting this object to itself. Further, if there is one arrow (f) that ends on an object, and another (g) that starts from the same object, there should then also be a composite arrow called g . f.
In Haskell this is modelled as a typeclass that represents the category of Haskell types as objects.
class Category cat where
id :: cat a a
(.) :: cat b c -> cat a b -> cat a c
Basic examples of a category are functions. Each function connects two types, for all types, there is the function id :: a -> a that connects the type (and the value) to itself. The composition of functions is the ordinary function composition.
In short, categories in Haskell base are things that behave like functions, i.e. you can put one after another with a generalized version of (.).
A Monoid
A monoid is a set with an unit element and an associative operation. This is modelled in Haskell as:
class Monoid a where
mempty :: a
mappend :: a -> a -> a
Common examples of monoids include:
set of integers, the element 0, and the operation (+).
set of positive integers, the element 1, and the operation (*).
set of all lists, the empty list [], and the operation (++).
These are modelled in Haskell as
newtype Sum a = Sum {getSum :: a}
instance (Num a) => Monoid (Sum a) where
mempty = Sum 0
mappend (Sum a) (Sum b) = Sum (a + b)
instance Monoid [a] where
mempty = []
mappend = (++)
Monoids are used to 'combine' and accumulate things. For example, the function mconcat :: Monoid a => [a] -> a, can be used to reduce a list of sums to single sum, or a nested list into a flat list. Consider this as a kind of generalization of (++) or (+) operations that in a way 'merge' two things.
A Functor
A functor in Haskell is a thing that quite directly generalizes the operation map :: (a->b) -> [a] -> [b]. Instead of mapping over a list, it maps over some structure, such as a list, binary tree, or even an IO operation. Functors are modelled like this:
class Functor f where
fmap :: (a->b) -> f a -> f b
Contrast this to the definition of the normal map function.
An Applicative Functor
Applicative functors can be seen as things with a generalized zipWith operation. Functors map over general structures one at the time, but with an Applicative functor you can zip together two or more structures. For the simplest example, you can use applicatives to zip together two integers inside the Maybe type:
pure (+) <*> Just 1 <*> Just 2 -- gives Just 3
Notice that the structure can affect the result, for example:
pure (+) <*> Nothing <*> Just 2 -- gives Nothing
Contrast this to the usual zipWith function:
zipWith (+) [1] [2]
Instead of of just lists, the applicative works for all kinds of structures. Additionally, the clever trickery with pure and (<*>) generalizes the zipping to work with any number of arguments. To see how this works, inspect the following types while keeping the concept of partially applied functions at hand:
instance (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
Notice also the similarity between fmap and (<*>).
A Monad
Monads are often used to model different computational contexts, such as non-deterministic, or side-effectful computations. Since there are already far too many monad tutorials, I will just recommend The best one, instead of writing yet another.
Relating to the ordinary list processing functions, monads generalize the function concat :: [[a]] -> [a] to work with many other sorts of structures besides lists. As a simple example, the monadic operation join can be used to flatten nested Maybe values:
join (Just (Just 42)) -- gives Just 42
join (Just (Nothing)) -- gives Nothing
How is this related to the use of Monads as a means of structuring computations? Consider a toy example where you do two consecutive queries from some database. The first query returns you some key value, with which you wish to do another lookup. The problem here is that the first value is wrapped inside Maybe, so you can't query with that directly. Instead, as maybe is a Functor, you could instead fmap the return value with the new query. This would give you two nested Maybe values like above. Another query would result in three layers of Maybes. This would be quite difficult to program with, but a monadic join gives you a way to flatten this structure, and work with just a single level of Maybes.
(I think I'll be editing this post a lot before it makes any sense..)
I think to understanding monads one needs to play with bind operator (>>=).
Heavilty influenced by [http://dev.stephendiehl.com/hask/#eightfold-path-to-monad-satori](Don't read the monad tutorials.)
My little play is the following:
1. Concat getLine and putStrLn
Adapted from http://www.haskellforall.com/2014/10/how-to-desugar-haskell-code.html
Prelude> f = getLine >>= \a -> putStrLn a
Prelude> f
abc
abc
Prelude>
and the signatures:
Prelude> :t getLine
getLine :: IO String
Prelude> :t (\a -> putStrLn a)
(\a -> putStrLn a) :: String -> IO ()
Prelude> :t f
f :: IO ()
Result: one can see parts of (>>=) :: Monad m => m a -> (a -> m b) -> m b signature.
2 . concat Maybe's
Adaptation from https://wiki.haskell.org/Simple_monad_examples
Prelude> g x = if (x == 0) then Nothing else Just (x + 1)
Prelude> Just 0 >>= g
Nothing
Prelude> Just 1 >>= g
Just 2
Result: fail "zero" is Nothing
3. Think of bind as joining the computations
... as described in https://www.slideshare.net/ScottWlaschin/functional-design-patterns-devternity2018
Related
I am learning about Applicative Functors and the pure function has the following type declaration:
pure :: a -> f a
I understand that the pure function takes a value of any type and returns an applicative value with that value inside it. So if the applicative instance was Maybe, pure 3 would give Just 3.
However, what happens when you apply pure to a value that's already inside an applicative value? E.g. what happens if you do something like pure Just 3?
What happens when you apply pure to a value that's already inside an applicative value?
It just gets wrapped in an additional layer. The end result is an applicative value nested inside another applicative value.
E.g. what happens if you do something like pure Just 3?
This is an interesting question, although probably not for the reasons you meant. The important point here is to distinguish pure (Just 3) — which was probably what you meant — from pure Just 3 = (pure Just) 3, which is what you wrote. This gives two scenarios:
pure (Just 3) simply applies pure to the value Just 3, which — as I discussed above — gives Just (Just 3), which is a nested applicative value.
(pure Just) 3 is an interesting case. Recall the types of pure and Just:
pure :: Applicative f => a -> f a
Just :: a -> Maybe a
-- so:
pure Just :: Applicative f => f (a -> Maybe a)
In other words, pure Just takes the function Just and wraps it inside an applicative value.
Next, we want to take pure Just and apply it to a value 3. But we can’t do this, since f (a -> Maybe a) is a value, not a function! So (pure Just) 3 should result in a type error.
…except it turns out to typecheck just fine! So we’re missing something. In this case, it turns out there is an applicative instance for functions:
instance Applicative ((->) r) where
pure x = \r -> x
(<*>) = _irrelevant_here
The syntax is a bit funny, but it basically means that r -> ... is an applicative. This particular instance is known as the Reader monad, and it’s very widely used. (For more about this particular data type, see e.g. here or here.) The idea is that r -> a can compute an a given an r input; in this case, pure x creates a function which ignores its input and returns x always, and f <*> x feeds the r input into both f and x, then combines the two. In this case, we’re only using pure, so it’s easy to evaluate (pure Just) 3 by hand:
(pure Just) 3
= (\r -> Just) 3
= Just
So the idea here is that pure wraps Just in an applicative value, which in this case happens to be a function; then, we apply this function to 3, which gets rid of the wrapper to reveal the original Just.
First of all, pure has the type:
pure :: Applicative f => a -> f a
To make things simpler, think of the kind of f
:k f
f :: * -> *
and the kind of a is *
then the type of a, is just a, any a, the most polymorphic of all (but with kind * remember). So you don't really care the value of a, you just have a restriction, and that's the typeclass Applicative, and the kind of f (remember * -> *)
so in this case:
gchi> pure 3 :: Maybe Int
ghci> Just 3
here f is Maybe and a is 3
In the same way
gchi> pure $ Just 3 :: Maybe (Maybe Int)
gchi> Just (Just 3)
here f is again Maybe and a is Just 3
and you can play a little changing the type to pure:
gchi> pure 3 :: [Double]
ghci> [3.0]
here, f is [], and a is 3
same way
ghci> pure [3] :: [[Double]]
ghci> [[3.0]]
finally here, f again, is [] and a is [3]
join is defined along with bind to flatten the combined data structure into single structure.
From type system view, (+) 7 :: Num a => a -> a could be considered as a Functor, (+) :: Num a => a -> a -> a could be considered as a Functor of Functor, how to get some intuition about it instead of just relying on type system? Why join (+) 7 === 14?
Even though it is possible to get the final result through manually stepping by the function binding process, it would be great if some intuition were given.
This is from the NICTA exercises.
-- | Binds a function on the reader ((->) t).
--
-- >>> ((*) =<< (+10)) 7
-- 119
instance Bind ((->) t) where
(=<<) ::
(a -> ((->) t b))
-> ((->) t a)
-> ((->) t b)
(f =<< a) t =
f (a t) t
-- | Flattens a combined structure to a single structure.
--
-- >>> join (+) 7
-- 14
join ::
Bind f =>
f (f a)
-> f a
join f =
id =<< f
*Course.State> :t join (+)
join (+) :: Num a => a -> a
*Course.State> :t join
join :: Bind f => f (f a) -> f a
*Course.State> :t (+)
(+) :: Num a => a -> a -> a
how to get some intuition about it instead of just relying on type system?
I'd rather say that relying on the type system is a great way to build a specific sort of intuition. The type of join is:
join :: Monad m => m (m a) -> m a
Specialised to (->) r, it becomes:
(r -> (r -> a)) -> (r -> a)
Now let's try to define join for functions:
-- join :: (r -> (r -> a)) -> (r -> a)
join f = -- etc.
We know the result must be a r -> a function:
join f = \x -> -- etc.
However, we do not know anything at all about what the r and a types are, and therefore we know nothing in particular about f :: r -> (r -> a) and x :: r. Our ignorance means there is literally just one thing we can do with them: passing x as an argument, both to f and to f x:
join f = \x -> f x x
Therefore, join for functions passes the same argument twice because that is the only possible implementation. Of course, that implementation is only a proper monadic join because it follows the monad laws:
join . fmap join = join . join
join . fmap return = id
join . return = id
Verifying that might be another nice exercise.
Going along with the traditional analogy of a monad as a context for computation, join is a method of combining contexts. Let's start with your example. join (+) 7. Using a function as a monad implies the reader monad. (+ 1) is a reader monad which takes the environment and adds one to it. Thus, (+) would be a reader monad within a reader monad. The outer reader monad takes the environment n and returns a reader of the form (n +), which will take a new environment. join simply combines the two environments so that you provide it once and it applies the given parameter twice. join (+) === \x -> (+) x x.
Now, more in general, let's look at some other examples. The Maybe monad represents potential failure. A value of Nothing is a failed computation, whereas a Just x is a success. A Maybe within a Maybe is a computation that could fail twice. A value of Just (Just x) is obviously a success, so joining that produces Just x. A Nothing or a Just Nothing indicates failure at some point, so joining the possible failure should indicate that the computation failed, i.e. Nothing.
A similar analogy can be made for the list monad, for which join is merely concat, the writer monad, which uses the monoidal operator <> to combine the output values in question, or any other monad.
join is a fundamental property of monads and is the operation that makes it significantly stronger than a functor or an applicative functor. Functors can be mapped over, applicatives can be sequences, monads can be combined. Categorically, a monad is often defined as join and return. It just so happens that in Haskell we find it more convenient to define it in terms of return, (>>=), and fmap, but the two definitions have been proven synonymous.
An intuition about join is that is squashes 2 containers into one. .e.g
join [[1]] => [1]
join (Just (Just 1)) => 1
join (a christmas tree decorated with small cristmas tree) => a cristmas tree
etc ...
Now, how can you join functions ? In fact functions, can be seen as a container.
If you look at a Hash table for example. You give a key and you get a value (or not). It's a function key -> value (or if you prefer key -> Maybe value).
So how would you join 2 HashMap ?
Let's say I have (in python style) h={"a": {"a": 1, "b": 2}, "b" : {"a" : 10, "b" : 20 }} how can I join it, or if you prefer flatten it ?
Given "a" which value should I get ? h["a"] gives me {"a":1, "b":2}. The only thing I can do with it is to find "a" again in this new value, which gives me 1.
Therefore join h equals to {"a":1, "b":20}.
It's the same for a function.
In Haskell we see Foldable and Traversable landing in Haskell prelude.
These both do operations on sequences.
Prelude Data.Sequence> map (\n -> replicate n 'a') [1,3,5]
["a","aaa","aaaaa"]
Prelude Data.Sequence> fmap (\n -> replicate n 'a') (1 <| 3 <| 5 <| empty)
fromList ["a","aaa","aaaaa"]
My question is is the equivalent of Haskell's Foldable and Traversable simply a sequence in Clojure?
Assumptions:
I realise that the equivalent of fmap in Haskell is m-fmap in Clojure.
No. Whilst any kind of Functor representing finite sequences of elements will be Traversable (hence Foldable), there are plenty of other structures which are Traversable, but which aren't sequence-like, in that they don't have an obvious notion of concatenation. There will be a way to obtain the sequence of contained elements, but the structure may consist of more than just that sequence.
What Traversable f means, in effect, is that structures with type f x contain finitely many elements of type x, and that there is some way to traverse the structure visiting each element of x exactly once. So things like "terms in a syntax, seen as containing variables" can be Traversable.
data Term x
= Var x
| Val Integer
| Add (Term x) (Term x)
instance Traversable Term where
traverse f (Var x) = pure Var <*> f x
traverse f (Val i) = pure (Val i)
traverse f (Add s t) = pure Add <*> traverse f s <*> traverse f t
You can always use traverse to do operations on all elements. We get fmap by taking pure = id and <*> to be ordinary application.
instance Functor Term where
fmap = fmapDefault
where
fmap :: (x -> y) -> Term x -> Term y
implements simultaneous renaming.
Meanwhile, the Foldable instance
instance Foldable Term where
foldMap = foldMapDefault
takes pure to give the neutral element of some monoid and <*> to the combining operation, so we get reduce-like operations. E.g.,
foldMap (:[]) :: Term x -> [x]
gives the list of variables occurring in a term. That is we can always obtain the sequence of elements from Traversable data, but the data might have structure other than those elements. Terms have structure other than variables (their Vals and Adds), and it's not so clear what "cons" means for syntax trees.
So, while more structures than sequences are Traversable, the Traversable interface offers you fewer sequence-like operations. The point of Traversable is to generalize map-like and reduce-like operations, not to capture list-ness.
I'd like to point out the Haskell wiki documentation on Foldable and Traversable.
First of all, Foldable and Traversable are two different type classes. As for Foldable, the comments made by the wiki page seem to suggest that it is pretty much the same as a Clojure sequence. Every Foldable has a representation as a list:
toList :: Foldable a => [a]
toList a = foldr (:) [] a
and (correct me if I'm wrong) it seems that folding over the structure is the same as folding over the associated list, i.e.:
foldr f b a = foldr f b (toList a)
In this equation the foldr on the left is the generic version whereas the one on the right is the one on lists.
The main difference between Haskell and Clojure here is that Clojure requires you to apply the toList function yourself to convert the data structure to a sequence before folding/reducing it. For flat data structures (i.e. lists, vectors, hash maps...) toList is just the identity function so you don't see it. On the other hand for something like trees you would need to call a function like tree-seq before folding it.
I've seen the term Free Monad pop up every now and then for some time, but everyone just seems to use/discuss them without giving an explanation of what they are. So: what are free monads? (I'd say I'm familiar with monads and the Haskell basics, but have only a very rough knowledge of category theory.)
Here's an even simpler answer: A Monad is something that "computes" when monadic context is collapsed by join :: m (m a) -> m a (recalling that >>= can be defined as x >>= y = join (fmap y x)). This is how Monads carry context through a sequential chain of computations: because at each point in the series, the context from the previous call is collapsed with the next.
A free monad satisfies all the Monad laws, but does not do any collapsing (i.e., computation). It just builds up a nested series of contexts. The user who creates such a free monadic value is responsible for doing something with those nested contexts, so that the meaning of such a composition can be deferred until after the monadic value has been created.
Edward Kmett's answer is obviously great. But, it is a bit technical. Here is a perhaps more accessible explanation.
Free monads are just a general way of turning functors into monads. That is, given any functor f Free f is a monad. This would not be very useful, except you get a pair of functions
liftFree :: Functor f => f a -> Free f a
foldFree :: Functor f => (f r -> r) -> Free f r -> r
the first of these lets you "get into" your monad, and the second one gives you a way to "get out" of it.
More generally, if X is a Y with some extra stuff P, then a "free X" is a a way of getting from a Y to an X without gaining anything extra.
Examples: a monoid (X) is a set (Y) with extra structure (P) that basically says it has an operation (you can think of addition) and some identity (like zero).
So
class Monoid m where
mempty :: m
mappend :: m -> m -> m
Now, we all know lists
data [a] = [] | a : [a]
Well, given any type t we know that [t] is a monoid
instance Monoid [t] where
mempty = []
mappend = (++)
and so lists are the "free monoid" over sets (or in Haskell types).
Okay, so free monads are the same idea. We take a functor, and give back a monad. In fact, since monads can be seen as monoids in the category of endofunctors, the definition of a list
data [a] = [] | a : [a]
looks a lot like the definition of free monads
data Free f a = Pure a | Roll (f (Free f a))
and the Monad instance has a similarity to the Monoid instance for lists
--it needs to be a functor
instance Functor f => Functor (Free f) where
fmap f (Pure a) = Pure (f a)
fmap f (Roll x) = Roll (fmap (fmap f) x)
--this is the same thing as (++) basically
concatFree :: Functor f => Free f (Free f a) -> Free f a
concatFree (Pure x) = x
concatFree (Roll y) = Roll (fmap concatFree y)
instance Functor f => Monad (Free f) where
return = Pure -- just like []
x >>= f = concatFree (fmap f x) --this is the standard concatMap definition of bind
now, we get our two operations
-- this is essentially the same as \x -> [x]
liftFree :: Functor f => f a -> Free f a
liftFree x = Roll (fmap Pure x)
-- this is essentially the same as folding a list
foldFree :: Functor f => (f r -> r) -> Free f r -> r
foldFree _ (Pure a) = a
foldFree f (Roll x) = f (fmap (foldFree f) x)
A free foo happens to be the simplest thing that satisfies all of the 'foo' laws. That is to say it satisfies exactly the laws necessary to be a foo and nothing extra.
A forgetful functor is one that "forgets" part of the structure as it goes from one category to another.
Given functors F : D -> C, and G : C -> D, we say F -| G, F is left adjoint to G, or G is right adjoint to F whenever forall a, b: F a -> b is isomorphic to a -> G b, where the arrows come from the appropriate categories.
Formally, a free functor is left adjoint to a forgetful functor.
The Free Monoid
Let us start with a simpler example, the free monoid.
Take a monoid, which is defined by some carrier set T, a binary function to mash a pair of elements together f :: T → T → T, and a unit :: T, such that you have an associative law, and an identity law: f(unit,x) = x = f(x,unit).
You can make a functor U from the category of monoids (where arrows are monoid homomorphisms, that is, they ensure they map unit to unit on the other monoid, and that you can compose before or after mapping to the other monoid without changing meaning) to the category of sets (where arrows are just function arrows) that 'forgets' about the operation and unit, and just gives you the carrier set.
Then, you can define a functor F from the category of sets back to the category of monoids that is left adjoint to this functor. That functor is the functor that maps a set a to the monoid [a], where unit = [], and mappend = (++).
So to review our example so far, in pseudo-Haskell:
U : Mon → Set -- is our forgetful functor
U (a,mappend,mempty) = a
F : Set → Mon -- is our free functor
F a = ([a],(++),[])
Then to show F is free, we need to demonstrate that it is left adjoint to U, a forgetful functor, that is, as we mentioned above, we need to show that
F a → b is isomorphic to a → U b
now, remember the target of F is in the category Mon of monoids, where arrows are monoid homomorphisms, so we need a to show that a monoid homomorphism from [a] → b can be described precisely by a function from a → b.
In Haskell, we call the side of this that lives in Set (er, Hask, the category of Haskell types that we pretend is Set), just foldMap, which when specialized from Data.Foldable to Lists has type Monoid m => (a → m) → [a] → m.
There are consequences that follow from this being an adjunction. Notably that if you forget then build up with free, then forget again, its just like you forgot once, and we can use this to build up the monadic join. since UFUF ~ U(FUF) ~ UF, and we can pass in the identity monoid homomorphism from [a] to [a] through the isomorphism that defines our adjunction,get that a list isomorphism from [a] → [a] is a function of type a -> [a], and this is just return for lists.
You can compose all of this more directly by describing a list in these terms with:
newtype List a = List (forall b. Monoid b => (a -> b) -> b)
The Free Monad
So what is a Free Monad?
Well, we do the same thing we did before, we start with a forgetful functor U from the category of monads where arrows are monad homomorphisms to a category of endofunctors where the arrows are natural transformations, and we look for a functor that is left adjoint to that.
So, how does this relate to the notion of a free monad as it is usually used?
Knowing that something is a free monad, Free f, tells you that giving a monad homomorphism from Free f -> m, is the same thing (isomorphic to) as giving a natural transformation (a functor homomorphism) from f -> m. Remember F a -> b must be isomorphic to a -> U b for F to be left adjoint to U. U here mapped monads to functors.
F is at least isomorphic to the Free type I use in my free package on hackage.
We could also construct it in tighter analogy to the code above for the free list, by defining
class Algebra f x where
phi :: f x -> x
newtype Free f a = Free (forall x. Algebra f x => (a -> x) -> x)
Cofree Comonads
We can construct something similar, by looking at the right adjoint to a forgetful functor assuming it exists. A cofree functor is simply /right adjoint/ to a forgetful functor, and by symmetry, knowing something is a cofree comonad is the same as knowing that giving a comonad homomorphism from w -> Cofree f is the same thing as giving a natural transformation from w -> f.
The Free Monad (data structure) is to the Monad (class) like the List (data structure) to the Monoid (class): It is the trivial implementation, where you can decide afterwards how the content will be combined.
You probably know what a Monad is and that each Monad needs a specific (Monad-law abiding) implementation of either fmap + join + return or bind + return.
Let us assume you have a Functor (an implementation of fmap) but the rest depends on values and choices made at run-time, which means that you want to be able to use the Monad properties but want to choose the Monad-functions afterwards.
That can be done using the Free Monad (data structure), which wraps the Functor (type) in such a way so that the join is rather a stacking of those functors than a reduction.
The real return and join you want to use, can now be given as parameters to the reduction function foldFree:
foldFree :: Functor f => (a -> b) -> (f b -> b) -> Free f a -> b
foldFree return join :: Monad m => Free m a -> m a
To explain the types, we can replace Functor f with Monad m and b with (m a):
foldFree :: Monad m => (a -> (m a)) -> (m (m a) -> (m a)) -> Free m a -> (m a)
A Haskell free monad is a list of functors. Compare:
data List a = Nil | Cons a (List a )
data Free f r = Pure r | Free (f (Free f r))
Pure is analogous to Nil and Free is analogous to Cons. A free monad stores a list of functors instead of a list of values. Technically, you could implement free monads using a different data type, but any implementation should be isomorphic to the above one.
You use free monads whenever you need an abstract syntax tree. The base functor of the free monad is the shape of each step of the syntax tree.
My post, which somebody already linked, gives several examples of how to build abstract syntax trees with free monads
I think a simple concrete example will help. Suppose we have a functor
data F a = One a | Two a a | Two' a a | Three Int a a a
with the obvious fmap. Then Free F a is the type of trees whose leaves have type a and whose nodes are tagged with One, Two, Two' and Three. One-nodes have one child, Two- and Two'-nodes have two children and Three-nodes have three and are also tagged with an Int.
Free F is a monad. return maps x to the tree that is just a leaf with value x. t >>= f looks at each of the leaves and replaces them with trees. When the leaf has value y it replaces that leaf with the tree f y.
A diagram makes this clearer, but I don't have the facilities for easily drawing one!
Trying to provide a “bridge” answer between the auper-simple answers here and the full answer.
So “free monads” build a “monad” out of any “functor”, so let’s take these in order.
Functors in detail
Some things are type-level adjectives, meaning they take a type-noun like “integers” and give you back a different type-noun like “lists of integers” or “pairs of strings with integers” or even “functions making strings out of integers.” To denote an arbitrary adjective let me use the stand-in word “blue”.
But then we notice a pattern that some of these adjectives are input-ish or output-ish in the noun they modify. For example “functions making strings out of __” is input-ish, “functions turning strings into __” is output-ish. The rule here involves me having a function X → Y, some adjective “blue” is outputtish, or a functor, if I can use such a function to transform a blue X into a blue Y. Think of “a firehose spraying Xs” and then you screw on this X → Y function and now your firehose sprays Ys. Or it is inputtish or a contravariant if it is the opposite, a vacuum cleaner sucking up Ys and when I screw this on I get a vacuum sucking up Xs. Some things are neither outputtish nor inputtish. Things that are both it turns out are phantom: they have absolutely nothing to do with the nouns that they describe, in the sense that you can define a function “coerce” which takes a blue X and makes a blue Y, but *without knowing the details of the types X or Y,” not even requiring a function between them.
So “lists of __” is outputtish, you can map an X → Y over a list of Xs to get a list of Ys. Similarly “a pair of a string and a __” is outputtish. Meanwhile “a function from __ to itself” is neither outputtish nor inputtish,” while “a string and a list of exactly zero __s” could be the “phantom” case maybe.
But yeah, that's all there is to functors in programming, they are just things that are mappable. If something is a functor it is a functor uniquely, there is at most only one way to generically map a function over a data structure.
Monads
A monad is a functor that in addition is both
Universally applicable, given any X, I can construct a blue X,
Can be repeated without changing the meaning much. So a blue-blue X is in some sense the same as just a blue X.
So what this means is that there is a canonical function collapsing any blue-blue __ to just a blue __. (And we of course add laws to make everything sane: if one of the layers of blue came from the universal application, then we want to just erase that universal application; in addition if we flatten a blue-blue-blue X down to a blue X, it should not make a difference whether we collapse the first two blues first or the second two first.)
The first example is “a nullable __”. So if I give you a nullable nullable int, in some sense I have not given you much more than a nullable int. Or “a list of lists of ints,” if the point is just to have 0 or more of them, then “a list of ints” works just fine and the proper collapse is concatenating all of the lists together into one super list.
Monads became big in Haskell because Haskell needed an approach to do things in the real world without violating its mathematically pure world where nothing really happens. The solution was to add is sort of watered down form of metaprogramming where we introduce an adjective of “a program which produces a __.” So how do I fetch the current date? Well, Haskell can't do it directly without unsafePerformIO but it will let you describe and compose the program which produces the current date. In this vision, you are supposed to describe a program which produces nothing called “Main.main,” and the compiler is supposed to take your description and hand you this program as a binary executable for you to run whenever you want.
Anyway “a program which produces a program which produce an int” doesn't buy you much over “a program which produces an int” so this turns out to be a monad.
Free Monads
Unlike functors, monads aren't uniquely monads. There is not just one monad instance for a given functor. So for example “a pair of an int and a __”, what are you doing with that int? You could add it, you could multiply it. If you make it a nullable int, you could keep the minimum non-null one or the maximum non-null one, or the leftmost non-null one or the rightmost non-null one.
The free monad for a given functor is the "boringest” construction, it is just “A free blue X is a bluen X for any n = 0, 1, 2, ...”.
It is universal because a blue⁰ X is just an X. And a free blue free blue X is a bluem bluen X which is just a bluem+n X. It implements “collapse” therefore by not implementing collapse at all, internally the blues are nested arbitrarily.
This also means you can defer exactly which monad you are choosing until a later date, later you can define a function which reduces a blue-blue X to a blue X and collapse all of these to blue0,1 X and then another function from X to blue X gives you blue1 X throughout.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is a monad?
I am learning to program in the functional language of Haskell and I came across Monads when studying parsers. I had never heard of them before and so I did some extra studying to find out what they are.
Everywhere I look in order to learn this topic just confuses me. I can't really find a simple definition of what a Monad is and how to use them. "A monad is a way to structure computations in terms of values and sequences of computations using those values" - eh???
Can someone please provide a simple definition of what a Monad is in Haskell, the laws associated with them and give an example?
Note: I know how to use the do syntax as I have had a look at I/O actions and functions with side-effects.
Intuition
A rough intuition would be that a Monad is a particular kind of container (Functor), for which you have two operations available. A wrapping operation return that takes a single element into a container. An operation join that merges a container of containers into a single container.
return :: Monad m => a -> m a
join :: Monad m => m (m a) -> m a
So for the Monad Maybe you have:
return :: a -> Maybe a
return x = Just x
join :: Maybe (Maybe a) -> Maybe a
join (Just (Just x) = Just x
join (Just Nothing) = Nothing
join Nothing = Nothing
Likewise for the Monad [ ] these operations are defined to be:
return :: a -> [a]
return x = [x]
join :: [[a]] -> [a]
join xs = concat xs
The standard mathematical definition of Monad is based on these return and join operators. However in Haskell the definition of the class Monad substitutes a bind operator for join.
Monads in Haskell
In functional programming languages these special containers are typically used to denote effectful computations. The type Maybe a would represent a computation that may or may not succeed, and the type [a] a computation that is non-deterministic. Particularly we're interested in functions with effects, i.e.those with types a->m b for some Monad m. And we need to be able to compose them. This can be done using either a monadic composition or bind operator.
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
(>>=) :: Monad m => m a -> (a -> m b) -> m b
In Haskell the latter is the standard one. Note that its type is very similar to the type of the application operator (but with flipped arguments):
(>>=) :: Monad m => m a -> (a -> m b) -> m b
flip ($) :: a -> (a -> b) -> b
It takes an effectful function f :: a -> m b and a computation mx :: m a returning values of type a, and performs the application mx >>= f. So how do we do this with Monads? Containers (Functors) can be mapped, and in this case the result is a computation within a computation which can then be flattened:
fmap f mx :: m (m b)
join (fmap f mx) :: m b
So we have:
(mx >>= f) = join (fmap f mx) :: m b
To see this working in practise consider a simple example with lists (non-deterministic functions). Suppose you have a list of possible results mx = [1,2,3] and a non-deterministic function f x = [x-1, x*2]. To calculate mx >>= f you begin by mapping mx with f and then you merge the results::
fmap f mx = [[0,2],[1,4],[2,6]]
join [[0,2],[1,4],[2,6]] = [0,2,1,4,2,6]
Since in Haskell the bind operator (>>=) is more important than join, for efficiency reasons in the latter is defined from the former and not the other way around.
join mx = mx >>= id
Also the bind operator, being defined with join and fmap, can also be used to define a mapping operation. For this reason Monads are not required to be instances of the class Functor. The equivalent operation to fmap is called liftM in the Monad library.
liftM f mx = mx >>= \x-> return (f x)
So the actual definitions for the Monads Maybe becomes:
return :: a -> Maybe a
return x = Just x
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
Nothing >>= f = Nothing
Just x >>= f = f x
And for the Monad [ ]:
return :: a -> [a]
return x = [x]
(>>=) :: [a] -> (a -> [b]) -> [b]
xs >>= f = concat (map f xs)
= concatMap f xs -- same as above but more efficient
When designing your own Monads you may find it easier to, instead of trying to directly define (>>=), split the problem in parts and figure out what how to map and join your structures. Having map and join can also be useful to verify that your Monad is well defined, in the sense that it satisfy the required laws.
Monad Laws
Your Monad should be a Functor, so the mapping operation should satisfy:
fmap id = id
fmap g . fmap f = fmap (g . f)
The laws for return and join are:
join . return = id
join . fmap return = id
join . join = join . fmap join
The first two laws specify that merging undoes wrapping. If you wrap a container in another one, join gives you back the original. If you map the contents of a container with a wrapping operation, join again gives you back what you initially had. The last law is the associativity of join. If you have three layers of containers you get the same result by merging from the inside or the outside.
Again you can work with bind instead of join and fmap. You get fewer but (arguably) more complicated laws:
return a >>= f = f a
m >>= return = m
(m >>= f) >>= g = m >>= (\x -> f x >>= g)
A monad in Haskell is something that has two operations defined:
(>>=) :: Monad m => m a -> (a -> m b) -> m b -- also called bind
return :: Monad m => a -> m a
These two operations need to satisfy certain laws that really might just confuse you at this point, if you don't have a knack for mathy ideas. Conceptually, you use bind to operate on values on a monadic level and return to create monadic values from "trivial" ones. For instance,
getLine :: IO String,
so you cannot modify and putStrLn this String -- because it's not a String but an IO String!
Well, we have an IO Monad handy, so not to worry. All we have to do is use bind to do what we want. Let's see what bind looks like in the IO Monad:
(>>=) :: IO a -> (a -> IO b) -> IO b
And if we place getLine at the left hand side of bind, we can make it more specific yet.
(>>=) :: IO String -> (String -> IO b) -> IO b
Okay, so getLine >>= putStrLn . (++ ". No problem after all!") would print the entered line with the extra content added. The right hand side is a function that takes a String and produces an IO () - that wasn't hard at all! We just go by the types.
There are Monads defined for a lot of different types, for instance Maybe and [a], and they behave conceptually in the same way.
Just 2 >>= return . (+2) would yield Just 4, as you might expect. Note that we had to use return here, because otherwise the function on the right hand side would not match the return type m b, but just b, which would be a type error. It worked in the case of putStrLn because it already produces an IO something, which was exactly what our type needed to match. (Spoiler: Expressions of shape foo >>= return . bar are silly, because every Monad is a Functor. Can you figure out what that means?)
I personally think that this is as far as intuition will get you on the topic of monads, and if you want to dive deeper, you really do need to dive into the theory. I liked getting a hang of just using them first. You can look up the source for various Monad instances, for instance the List ([]) Monad or Maybe Monad on Hoogle and get a bit smarter on the exact implementations. Once you feel comfortable with that, have a go at the actual monad laws and try to gain a more theoretical understanding for them!
The Typeclassopedia has a section about Monad (but do read the preceding sections about Functor and Applicative first).