When I compare the binary operations of the Applicative and Monad type class
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(=<<) :: Monad m => (a -> m b) -> m a -> m b
two differences become apparent:
ap expects a normal, pure function, whereas bind expects a monadic action, which must return a monad of the same type
with ap the sequence of actions is determined by the applicative, whereas with bind the monadic action can determine the control flow
So monads give me additional expressive power. However, since they no longer accept normal, pure functions, this expressiveness seems to come at the expense of code reuse.
My conclusion might be somewhat naive or even false, since I have merely little experience with Haskell and monadic computations. Any light in the dark is appreciated!
If you have pure function g :: a -> b you can make it be either Applicative version by
pure g :: Applicative f => f (a -> b)
or Monadish by
pure . g :: Applicative f => a -> f b
So you don't lose any code reuse in your sense.
Code reuse is only an advantage if you can reuse code to do what you actually want.
GHCi> putStrLn =<< getLine
Sulfur
Sulfur
GHCi>
Here, (=<<) picks the String result produced in an IO context by getLine and feeds it to putStrLn, which then prints said result.
GHCi> :t getLine
getLine :: IO String
GHCi> :t putStrLn
putStrLn :: String -> IO ()
GHCi> :t putStrLn =<< getLine
putStrLn =<< getLine :: IO ()
Now, in the type of fmap/(<$>)...
GHCi> :t (<$>)
(<$>) :: Functor f => (a -> b) -> f a -> f b
... it is perfectly possible for b to be IO (), and therefore nothing stops us from using putStrLn with it. However...
GHCi> putStrLn <$> getLine
Sulfur
GHCi>
... nothing will be printed.
GHCi> :t putStrLn <$> getLine
putStrLn <$> getLine :: IO (IO ())
Executing an IO (IO ()) action won't execute the inner IO () action. To do that, we need the additional power of Monad, either by replacing (<$>) with (=<<) or, equivalently, by using join on the IO (IO ()) value:
GHCi> :t join
join :: Monad m => m (m a) -> m a
GHCi> join (putStrLn <$> getLine)
Sulfur
Sulfur
GHCi>
Like chi, I also have trouble understanding the premises of your question. You seem to expect that one of Functor, Applicative and Monad will turn out to be better than the others. That is not the case. We can do more things with Applicative than with Functor, and even more with Monad. If you need the additional power, use a suitably powerful class. If not, using a less powerful class will lead to simpler, clearer code and a broader range of available instances.
The reason for this question was my too schematic understanding of the relations between the functor, applicative and monad class. I thought it was only about reusing pure functions.
(<*>) essentially says give me an applicative of functions and a bunch of applicatives of values and I will apply them according to my rules.
(=<<) essentially says give me a function (a -> m b) and a monad and I will feed (a -> m b) with the value of the monad and leave it to (a -> m b) to produce and return a transformed value wrapped in the same monad.
Of course, the applicative code will be more concise and better reusable, because the mechanism of how a sequence of actions is executed is defined exclusively within (<*>). However, applicative sequences are also somehow mechanic. So when you want to control the flow of the sequence or the "shape" of the resulting structure, you need the extra power of monads, which leads to more verbose code.
I think this question isn't particularly helpful and if people vote for closing, I would have no problem deleting it.
Related
I'm new to functional programming (coming from javascript), and I'm having a hard time telling the difference between the two, which is also messing with my understand of functors vs. monads.
Functor:
class Functor f where
fmap :: (a -> b) -> f a -> f b
Monad (simplified):
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
fmap takes a function and a functor, and returns a functor.
>>= takes a function and a monad, and returns a monad.
The difference between the two is in the function parameter:
fmap - (a -> b)
>>= - (a -> m b)
>>= takes a function parameter that returns a monad. I know that this is significant, but I'm having difficulty seeing how this one slight thing makes monads much more powerful than functors. Can someone explain?
Well, (<$>) is an alias for fmap, and (=<<) is the same as (>>=) with the arguments swapped:
(<$>) :: (x -> y) -> b x -> b y
(=<<) :: (x -> b y) -> b x -> b y
The difference is now fairly clear: with the bind function, we apply a function that returns a b y rather than a y. So what difference does that make?
Consider this small example:
foo <$> Just 3
Notice that (<$>) will apply foo to 3, and put the result back into a Just. In other words, the result of this computation cannot be Nothing. On the contrary:
bar =<< Just 3
This computation can return Nothing. (For example, bar x = Nothing will do it.)
We can do a similar thing with the list monad:
foo <$> [Red, Yellow, Blue] -- Result is guaranteed to be a 3-element list.
bar =<< [Red, Yellow, Blue] -- Result can be ANY size.
In short, with (<$>) (i.e., fmap), the "structure" of the result is always identical to the input. But with (=<<) (i.e., (>>=)), the structure of the result can change. This allows conditional execution, reacting to input, and a whole bunch of other things.
Short answer is that if you can turn m (m a) into m a in a way which makes sense then it's a Monad. This is possible for all Monads but not necessarily for Functors.
I think the most confusing thing is that all of the common examples of Functors (e.g. List, Maybe, IO) are also Monads. We need an example of something that is a Functor but not a Monad.
I'll use an example from a hypothetical calendar program. The following code defines an Event Functor which stores some data that goes with the event and the time that it occurs.
import Data.Time.LocalTime
data Event a = MkEvent LocalTime a
instance Functor Event where
fmap f (MkEvent time a) = MkEvent time (f a)
The Event object stores the time that the event occurs and some extra data that can be changed using fmap. Now lets try and make it a Monad:
instance Monad Event where
(>>=) (MkEvent timeA a) f = let (MkEvent timeB b) = f a in
MkEvent <notSureWhatToPutHere> b
We find that we can't because you will end up with two LocalTime objects. timeA from the given Event and timeB from the Event given by the result of f a. Our Event type is defined as having only one LocalTime (time) that it occurs at and so making it a Monad isn't possible without turning two LocalTimes into one. (There may be some case where doing so might make sense and so you could turn this into a monad if you really wanted to).
Assume for a moment that IO were just a Functor, and not a Monad. How could we sequence two actions? Say, like getChar :: IO Char and putChar :: Char -> IO ().
We could try mapping over getChar (an action that, when executed, reads a Char from stdin) using putChar.
fmap putChar getChar :: IO (IO ())
Now we have a program that, when executed, reads a Char from stdin and produces a program that, when executed, writes the Char to stdout. But what we actually want is a program that, when executed, reads a Char from stdin and writes the Char to stdout. So we need a "flattening" (in the IO case, "sequencing") function with type:
join :: IO (IO ()) -> IO ()
Functor by itself does not provide this function. But it is a function of Monad, where it has the more general type:
join :: Monad m => m (m a) -> m a
What does all of this have to do with >>=? As it happens, monadic bind is just a combination of fmap and join:
:t \m f -> join (fmap f m)
(Monad m) => m a1 -> (a1 -> m a) -> m a
Another way of seeing the difference is that fmap never changes the overall structure of the mapped value, but join (and therefore >>= as well) can do that.
In terms of IO actions, fmap will never cause addicional reads/writes or other effects. But join sequences the read/writes of the inner action after those of the outer action.
I want to sequentially compose two monad actions in Haskell, discarding any value produced by the second, and passing the argument to both actions. Currently I'm using a do-block like this:
ask = do
result <- getLine
putStrLn result
return result
I was hoping to write this a little more point free and neat, so I tried this:
ask' = getLine <* putStrLn
However, this doesn't even type check and the problem is that <* does not transfer the result of the first action to the second. I want to chain the actions like >>= does, but not change the result. The type should be (a -> m b) -> (a -> m c) -> (a -> m b), but Hoogle yields no suitable results. What would be an operator to achieve this function composition?
As a tendency, if you use one value in two different places it probably is a good idea to give it a name in a clear do block, rather than pressing on pointless style.
The abstract concept of splitting up information flow to different actions is captured by cartesian monoidal categories, known to Haskellers as arrows. In your case, you're basically working in the IO Kleisli category:
import Prelude hiding (id)
import Control.Arrow
ask' :: Kleisli IO () String
ask' = Kleisli (\()->getLine) >>> (putStrLn &&& id) >>> arr snd
I don't think it's a good idea to write such code.
I want to sequentially compose two monad actions in Haskell, discarding any value produced by the second, and passing the argument to both actions.
This sounds to me like a Reader—the function type r -> m a is isomorphic to ReaderT r m a, and the monad works by implicitly plugging in the same r value into all the "holes." So for example:
import Control.Applicative
import Control.Monad.Reader
example :: IO String
example = getLine >>= discarding putStrLn
discarding :: Monad m => (a -> m b) -> a -> m a
discarding action = runReaderT (ReaderT action *> ask)
The operator you want is then something like:
action `thingy` extra = action >>= discarding extra
But of course discarding has a simpler implementation:
discarding :: Applicative f => (a -> f b) -> a -> f a
discarding action a = action a *> return a
...so in the end I think this is really code golf. But in a more complex program where this is a common pattern at a larger scale it might be worth a shot. Basically, if you have:
a0 :: r -> m a0
a1 :: r -> m a1
.
.
.
an :: r -> m an
Then it follows that:
ReaderT a0 :: ReaderT r m a0
ReaderT a1 :: ReaderT r m a1
.
.
.
ReaderT an :: ReaderT r m an
And then:
runReaderT (ReaderT a0 <* ReaderT a1 <* ... <* ReaderT an) :: r -> m a0
For completeness, in this particular case (the IO) monad, you could also abuse bracket for this purpose:
bracket getLine putStrLn return
But I strongly discourage it, as this will be much less readable than the original do-notation block, it's just ugly.
As already mentioned, in this particular case naming the result seems the best way.
See also Should do-notation be avoided in Haskell?
This is the signature of the well know >>= operator in Haskell
>>= :: Monad m => m a -> (a -> m b) -> m b
The question is why type of the function is
(a -> m b)
instead of
(a -> b)
I would say the latter one is more practical because it allows straightforward integration of existing "pure" functions in the monad being defined.
On the contrary, it seems not difficult to write a general "adapter"
adapt :: (Monad m) => (a -> b) -> (a -> m b)
but anyway I regard more probable that you already have (a -> b) instead of (a -> m b).
Note. I explain what I mean by "pratical" and "probable".
If you haven't defined any monad in a program yet, then, the functions you have are "pure" (a -> b) and you will have 0 functions of the type (a -> m b) just because you have not still defined m. If then you decide to define a monad m it comes the need of having new a -> m b functions defined.
Basically, (>>=) lets you sequence operations in such a way that latter operations can choose to behave differently based on earlier results. A more pure function like you ask for is available in the Functor typeclass and is derivable using (>>=), but if you were stuck with it alone you'd no longer be able to sequence operations at all. There's also an intermediate called Applicative which allows you to sequence operations but not change them based on the intermediate results.
As an example, let's build up a simple IO action type from Functor to Applicative to Monad.
We'll focus on a type GetC which is as follows
GetC a = Pure a | GetC (Char -> GetC a)
The first constructor will make sense in time, but the second one should make sense immediately—GetC holds a function which can respond to an incoming character. We can turn GetC into an IO action in order to provide those characters
io :: GetC a -> IO a
io (Pure a) = return a
io (GetC go) = getChar >>= (\char -> io (go char))
Which makes it clear where Pure comes from---it handles pure values in our type. Finally, we're going to make GetC abstract: we're going to disallow using Pure or GetC directly and allow our users access only to functions we define. I'll write the most important one now
getc :: GetC Char
getc = GetC Pure
The function which gets a character then immediately considers is a pure value. While I called it the most important function, it's clear that right now GetC is pretty useless. All we can possibly do is run getc followed by io... to get an effect totally equivalent to getChar!
io getc === getChar :: IO Char
But we'll build up from here.
As stated at the beginning, the Functor typeclass provides a function exactly like you're looking for called fmap.
class Functor f where
fmap :: (a -> b) -> f a -> f b
It turns out that we can instantiate GetC as a Functor so let's do that.
instance Functor GetC where
fmap f (Pure a) = Pure (f a)
fmap f (GetC go) = GetC (\char -> fmap f (go char))
If you squint, you'll notice that fmap affects the Pure constructor only. In the GetC constructor it just gets "pushed down" and deferred until later. This is a hint as to the weakness of fmap, but let's try it.
io getc :: IO Char
io (fmap ord getc) :: IO Int
io (fmap (\c -> ord + 1) getc) :: IO Int
We've gotten the ability to modify the return type of our IO interpretation of our type, but that's about it! In particular, we're still limited to getting a single character and then running back to IO to do anything interesting with it.
This is the weakness of Functor. Since, as you noted, it deals only with pure functions it gets stuck "at the end of a computation" modifying the Pure constructor only.
The next step is Applicative which extends Functor like this
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
In other words it extends the notion of injecting pure values into our context and allowing pure function application to cross over the data type. Unsurprisingly, GetC instantiates Applicative too
instance Applicative GetC where
pure = Pure
Pure f <*> Pure x = Pure (f x)
GetC gof <*> getcx = GetC (\char -> gof <*> getcx)
Pure f <*> GetC gox = GetC (\char -> fmap f (gox char))
Applicative allows us to sequence operations and that might be clear from the definition already. In fact, we can see that (<*>) pushes character application forward so that the GetC actions on either side of (<*>) get performed in order. We use Applicative like this
fmap (,) getc <*> getc :: GetC (Char, Char)
and it allows us to build incredibly interesting functions, much more complex than just Functor would. For instance, we can already form a loop and get an infinite stream of characters.
getAll :: GetC [Char]
getAll = fmap (:) getc <*> getAll
which demonstrates the nature of Applicative being able to sequence actions one after another.
The problem is that we can't stop. io getAll is an infinite loop because it just consumes characters forever. We can't tell it to stop when it sees '\n', for instance, because Applicatives sequence without noticing earlier results.
So let's go the final step an instantiate Monad
instance Monad GetC where
return = pure
Pure a >>= f = f a
GetC go >>= f = GetC (\char -> go char >>= f)
Which allows us immediately to implement a stopping getAll
getLn :: GetC String
getLn = getc >>= \c -> case c of
'\n' -> return []
s -> fmap (s:) getLn
Or, using do notation
getLn :: GetC String
getLn = do
c <- getc
case c of
'\n' -> return []
s -> fmap (s:) getLn
So what gives? Why can we now write a stopping loop?
Because (>>=) :: m a -> (a -> m b) -> m b lets the second argument, a function of the pure value, choose the next action, m b. In this case, if the incoming character is '\n' we choose to return [] and terminate the loop. If not, we choose to recurse.
So that's why you might want a Monad over a Functor. There's much more to the story, but those are the basics.
The reason is that (>>=) is more general. The function you're suggesting is called liftM and can be easily defined as
liftM :: (Monad m) => (a -> b) -> (m a -> m b)
liftM f k = k >>= return . f
This concept has its own type class called Functor with fmap :: (Functor m) => (a -> b) -> (m a -> m b). Every Monad is also a Functor with fmap = liftM, but for historical reasons this isn't (yet) captured in the type-class hierarchy.
And adapt you're suggesting can be defined as
adapt :: (Monad m) => (a -> b) -> (a -> m b)
adapt f = return . f
Notice that having adapt is equivalent to having return as return can be defined as adapt id.
So anything that has >>= can also have these two functions, but not vice versa. There are structures that are Functors but not Monads.
The intuition behind this difference is simple: A computation within a monad can depend on the results of the previous monads. The important piece is (a -> m b) which means that not just b, but also its "effect" m b can depend on a. For example, we can have
import Control.Monad
mIfThenElse :: (Monad m) => m Bool -> m a -> m a -> m a
mIfThenElse p t f = p >>= \x -> if x then t else f
but it's not possible to define this function with just Functor m constraint, using just fmap. Functors only allow us to change the value "inside", but we can't take it "out" to decide what action to take.
As others have said, your bind is the fmap function of the Functor class, a.k.a <$>.
But why is it less powerful than >>=?
it seems not difficult to write a general "adapter"
adapt :: (Monad m) => (a -> b) -> (a -> m b)
You can indeed write a function with this type:
adapt f x = return (f x)
However, this function is not able to do everything that we might want >>='s argument to do. There are useful values that adapt cannot produce.
In the list monad, return x = [x], so adapt will always return a single-element list.
In the Maybe monad, return x = Some x, so adapt will never return None.
In the IO monad, once you retrieved the result of an operation, all you can do is compute a new value from it, you can't run a subsequent operation!
etc. So in short, fmap is able to do fewer things than >>=. That doesn't mean it's useless -- it wouldn't have a name if it was :) But it is less powerful.
The whole 'point' of the monad really (that puts it above functor or applicative) is that you can determine the monad you 'return' based on the values/results of the left hand side.
For example, >>= on a Maybe type allows us to decide to return Just x or Nothing. You'll note that using functors or applicative, it is impossible to "choose" to return Just x or Nothing based on the "sequenced" Maybe.
Try implementing something like:
halve :: Int -> Maybe Int
halve n | even n = Just (n `div` 2)
| otherwise = Nothing
return 24 >>= halve >>= halve >>= halve
with only <$> (fmap1) or <*> (ap).
Actually the "straightforward integration of pure code" that you mention is a significant aspect of the functor design pattern, and is very useful. However, it is in many ways unrelated to the motivation behind >>= --- they are meant for different applications and things.
I had the same question for a while and was thinking why bother with a -> m b once mapping a -> b to m a -> m b looks more natural. This is simialr to asking "why we need a monad given the functor".
The little answer that I give to myself is that a -> m b accounts for side-effects or other complexities that you would not capture with function a -> b.
Even better wording form here (highly recommend):
monadic value M a can itself be seen as a computation. Monadic functions represent computations that are, in some way, non-standard, i.e. not naturally supported by the programming language. This can mean side effects in a pure functional language or asynchronous execution in an impure functional language. An ordinary function type cannot encode such computations and they are, instead, encoded using a datatype that has the monadic structure.
I'd put emphasis on ordinary function type cannot encode such computations, where ordinary is a -> b.
I think that J. Abrahamson's answer points to the right reason:
Basically, (>>=) lets you sequence operations in such a way that latter operations can choose to behave differently based on earlier results. A more pure function like you ask for is available in the Functor typeclass and is derivable using (>>=), but if you were stuck with it alone you'd no longer be able to sequence operations at all.
And let me show a simple counterexample against >>= :: Monad m => m a -> (a -> b) -> m b.
It is clear that we want to have values bound to a context. And perhaps we will need to sequentially chain functions over such "context-ed values". (This is just one use case for Monads).
Take Maybe simply as a case of "context-ed value".
Then define a "fake" monad class:
class Mokad m where
returk :: t -> m t
(>>==) :: m t1 -> (t1 -> t2) -> m t2
Now let's try to have Maybe be an instance of Mokad
instance Mokad Maybe where
returk x = Just x
Nothing >>== f = Nothing
Just x >>== f = Just (f x) -- ????? always Just ?????
The first problem appears: >>== is always returning Just _.
Now let's try to chain functions over Maybe using >>==
(we sequentially extract the values of three Maybes just to add them)
chainK :: Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int
chainK ma mb mc = md
where
md = ma >>== \a -> mb >>== \b -> mc >>== \c -> returk $ a+b+c
But, this code doesn't compile: md type is Maybe (Maybe (Maybe Int)) because every time >>== is used, it encapsulates the previous result into a Maybe box.
And on the contrary >>= works fine:
chainOK :: Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int
chainOK ma mb mc = md
where
md = ma >>= \a -> mb >>= \b -> mc >>= \c -> return (a+b+c)
In a previous question, I tried to ask about how to mix pure and monadic functions by piping them together, but because I may have worded my question wrong and my example was too simplistic, I think the discussion went the wrong direction, so I think I'll try again.
Here is an example function that mixes pure and monadic filters. In this example, there are some pure filters sequenced in-between monadic filters to try to reduce the amount of work.
findFiles target =
getDirectoryContents target >>=
return . filter (not . (=~ "[0-9]{8}\\.txt$")) >>=
return . filter (=~ "\\.txt$") >>=
filterM doesFileExist >>=
mapM canonicalizePath
The benefit of writing it this way, where pure functions are mixed in using return, is that there is a visual flow of data from top to bottom. No need for temporary variables, fmap, <$> or the like.
Ideally, I can get rid of the returns to make it cleaner. I had the idea of using some operator:
(|>=) :: Monad m => a -> (a -> m b) -> m b
a |>= b = (return a) >>= b
But I don't know how to write this function to avoid operator precedence problems. Does this already exist? It is similar to <$> but the "other direction". If not, how do I make this operator work?
More generally, is there a good way to write code in this piping fashion, or need I settle for fmaps and temporary variables like as described in my previous question?
Ugh. As simple as this:
infixl 1 |>=
(|>=) = flip fmap
findFiles target =
getDirectoryContents target |>=
filter (not . (=~ "[0-9]{8}\\.txt$")) |>=
filter (=~ "\\.txt$") >>=
filterM doesFileExist >>=
mapM canonicalizePath
Seconding DiegoNolan, there's no prize for the pointest-free code and no shame in using do-notation, binding intermediate values with either a monadic assignment (x <- ...) or a good old-fashioned let. The heirs to your code will thank you.
That said, if you can't bear points, you might be a category theorist. Seriously, you can take a page from John Hughes (see Programming with Arrows) and write your pipeline like this:
import Control.Arrow
findFiles = runKleisli $
Kleisli getDirectoryContents >>>
arr (filter (not . (=~ "[0-9]{8}\\.txt$"))) >>>
arr (filter (=~ "\\.txt$")) >>>
Kleisli (filterM doesFileExist) >>>
Kleisli (mapM canonicalizePath)
This is probably a little more principled than monkeying around with one's own special bind operators, but still uglier than the plain pointed style if you ask me. De gustibus non est disputandum, as the Romans always used to say about garum.
Use (<$>), also known as fmap, for mapping pure functions into a functor. Most monads have instances of functors. If they don't have one then you can use liftM
Looking at the types
liftM :: Monad m => (a -> b) -> m a -> m b
(<$>) :: Functor f => (a -> b) -> f a -> f b
Yours would look like this (haven't checken in ghc).
findFiles target =
((filter (not . (=~ "[0-9]{8}\\.txt$")) .
filter (=~ "\\.txt$") ) <$>
getDirectoryContents target) >>=
filterM doesFileExist >>=
mapM canonicalizePath
But at this point you're probably just better off using do notation and let.
You'll want a few extra operators, one to handle each case
Monad -> Monad
Monad -> Pure
Pure -> Monad
Pure -> Pure
You already have the Monad -> Monad case (>>=), and as I described in my answer to your last question, you could use |>= for the Pure -> Monad case, but you'll still need Monad -> Pure one. That's going to be tricky, since the only type-safe way to do it is by having that operator transform your pure function into a monadic one. I'd recommend the following set of operators
Monad -> Monad >>= m a -> (a -> m b) -> m b
Monad -> Pure >|= m a -> (a -> b) -> m b
Pure -> Monad |>= a -> (a -> m b) -> m b
Pure -> Pure ||= (a -> b) -> (b -> c) -> (a -> c)
Using the convention that > means "monad" and | means "pure", and all end with = meaning "to function". Hopefully the type signatures will make sense with the implementations:
import Data.Char (toUpper)
import Control.Monad (liftM)
infixl 1 |>=
(|>=) :: Monad m => a -> (a -> m b) -> m b
a |>= b = b a
infixl 1 >|=
(>|=) :: Monad m => m a -> (a -> b) -> m b
a >|= b = liftM b a
infixr 9 ||=
(||=) :: (a -> b) -> (b -> c) -> a -> c
a ||= b = b . a
And an example
test :: IO ()
test =
getLine >|=
filter (/= 't') ||=
map toUpper >>=
putStrLn
> test
testing
ESING
>
This is also equivalent to
test :: IO ()
test =
getLine >|=
filter (/= 't') >|=
map toUpper >>=
putStrLn
But the extra ||> combination would let you actually compose those functions, which has a different implementation under the hood than feeding them through monadic actions.
However, I would still urge you to use the idiomatic way of doing this by using fmap, do notation, and temporary variables. It'll be much clearer to anyone else that looks at the code, and that includes you in 2 months' time.
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).