I'm trying to improve my understanding of Applicatives and Monads by implementing their function instances in Javascript. My knowledge of Haskell is limited and I hope that my question makes sense at all.
Here are my implementations of fmap, <*> and >>= for the Functor, Applicative and Monad typeclasses in Javascript:
const fmap = f => g => x => f(g(x)); // B combinator
const apply = f => g => x => f(x) (g(x)); // S combinator
const bind = f => g => x => g(f(x)) (x); // ?
I am not sure whether bind is the correct translation of the Haskell implementation:
(>>=) :: (r -> a) -> (a -> (r -> b)) -> r -> b
instance Monad ((->) r) where
f >>= k = \ r -> k (f r) r
Provided that bind is correct, how is it interpreted? I know that an Applicative can sequence effectful computations. I also know that a Monad in addition allows you to determine a next effect according to the result of a previous one.
I can see the sequences (eager evaluation order in Javascript):
apply: f(x) ... g(x) ... lambda(result of g) ... result of lambda
bind: f(x) ... g(result of f) ... lambda(x) ... result of lambda
However, the bind function looks pretty weird. Why are f and g nested the other way around? How is the specific Monad behavior (determines a next effect according to a previous one) reflected in this implementation? Actually g(f(x)) (x) looks like a function composition with flipped arguments, where g is a binary function.
When I apply apply/bind with an unary and a binary function, they yield the same result. This doesn't make much sense.
A few footnotes to Lee's answer:
However, the bind function looks pretty weird. Why are f and g
nested the other way around?
Because bind is backwards. Compare (>>=) and its flipped version (=<<):
(>>=) :: Monad m => m a -> (a -> m b) -> m b
(=<<) :: Monad m => (a -> m b) -> m a -> m b
Or, in your specific example:
(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b)
(=<<) :: (a -> (r -> b)) -> (r -> a) -> (r -> b)
While in practice we tend to use (>>=) more often than (=<<) (because of how (>>=), syntactically speaking, lends itself well to the kind of pipeline monads are often used to build), from a theoretical point of view (=<<) is the most natural way of writing it. In particular, the parallels and differences with fmap/(<$>) and (<*>) are much more obvious:
(<$>) :: Functor f => (a -> b) -> f a -> f b
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
(=<<) :: Monad f => (a -> f b) -> f a -> f b
When I apply apply/bind with an unary and a binary function, they yield the same result. This doesn't make much sense.
That is an accidental fact about the function instances. Let's put the specialised signatures side by side:
(<*>) :: (r -> (a -> b)) -> (r -> a) -> (r -> b)
(=<<) :: (a -> (r -> b)) -> (r -> a) -> (r -> b)
Monad goes beyond Applicative by providing the means to determine the next effect according to previous results (as opposed to "previous effect" -- Applicative can do that already). The effect, in this case, consists of a function that generates values given an argument of type r. Now, since functions with multiple arguments (i.e. functions that return functions) can be flipped, it happens that there is no significant difference between (r -> (a -> b)) and (a -> (r -> b)) (flip can trivially change one into the other), which makes the Monad instance for (->) r entirely equivalent to the Applicative one.
The values in the monad instance for functions have type r -> a for some fixed type r. The function (a -> (r -> b)) given to (>>=) allows you to choose the next function to return given the result from the current value (a function r -> a). f r has type a and k (f r) has type r -> b which is the next function to apply.
In your code g(f(x)) is therefore a function which expects a single argument of type r. The caller of bind can choose this function based on the value returned by the previous function e.g.
var inc = x => x + 1;
var f = bind(inc)(function(i) {
if(i <= 5) { return x => x * 2; }
else { return x => x * 3; }
});
The function will be given x as an input and can choose the next stage in the computation based on the result of inc(x) e.g.
f(2) //4;
f(5) //15;
Related
I can't understand the difference between Dot (function composition) and bind (>>=) .
If I understand, these two ways take the previous result of a function for a new function.
So what is the difference ?
They are pretty different. Let's look at their signatures:
(.) :: (b -> c) -> (a -> b) -> (a -> c)
(>>=) :: (Monad m) => m a -> (a -> m b) -> m b
As you said, the function composition is just a way to pass a result of one function as an argument to another one like this:
f = g . h
is equivalent to
f x = g (h x)
You can think about is as some kind of a "conveyor", where your value goes through several processing steps.
But (>>=) is quite different. It is related to such context as monad which is something like some value in some context (it's highly recommended to read the previous link if you aren't familiar with it).
So let x be some value in a context. Our context will be nullability (Maybe monad), and the value is 2. So, x = Just 2. We could, for example, get it as a result of a lookup from some associative container (such operation might fail, that's the reason why it is Maybe Int, but not Int).
Now we want to pass our x to some arithmetic function f that accepts just Int and may fail, so its signature looks like:
f :: Int -> Maybe Int
We can't just pass our value because of type mismatch. We could unpack x and handle some cases with if, but we could do that in almost all other languages. In haskell, we can use (>>=):
x >>= f
This allows as to chain the effects:
if x is Nothing, then the result is Nothing immediately
else x is unpacked and passed to f
This is a generalization of the operator ?., that you could see in some languages:
x = a?.func1()?.func2();
which checks for null at each "step" and stops immediately if hits null or returns the value in case of success. In haskell it looks like:
x = a >>= func1 >>= func2
However, bind with monads is a much more powerful concept, allowing you, for example, to emulate stateful computations in a language without mutability like haskell.
(>>=) is a form of function application.
(>>=) :: Monad m => m a -> (a -> m b) -> m b
flip ($) :: a -> (a -> b) -> b
It takes a value, but "extracts" part of it in order to apply the given function. Chaining two functions, like x >>= f >>= g requires the argument type of g to be different from (but at the same type similar to) the return type of f, unlike composition, which requires the types to match exactly.
Composed with return, it
really is just function application, but restricted to certain kinds of functions.
flip ($) :: a -> (a -> b) -> b
(>>=) . return :: Monad m => a -> (a -> m b) -> m b
(.) is more like (<=<) (from Control.Monad).
(.) :: (b -> c) -> (a -> b) -> a -> c
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
But again, instead of simply passing the result of one function to another, it first "extracts" a value before doing application.
In Control.Lens.Lens, there is a function
modifying :: MonadState s m => ASetter s s a b -> (a -> b) -> m ()
which allows the value under a lens on the MonadState state to be transformed by a pure function (a -> b).
However, we may want to allow the transform function to fail in m, requiring it to have type (a -> m b).
I've looked through the lens library for such a function, but I can't find one, so I implemented:
modifyingM l f = use l >>= f >>= assign l
Which does the trick, but I was wondering if there is a function already in the lens library that will do this.
I don't see anything like that. ASetter is defined
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
so it's not powerful enough for the job (and Setter can't do it either). It turns out, on the other hand, that a Lens is a bit stronger than necessary. Let's consider, then, how to do it with a Traversal.
type Traversal s t a b =
forall f. Applicative f => (a -> f b) -> s -> f t
So
Traversal s s a b =
forall f. Applicative f => (a -> f b) -> s -> f s
Which Applicative do we want? m seems like the obvious one to try. When we pass the traversal a -> m b, we get back s -> m s. Great! As usual for lens, we'll actually only require the user to provide an ATraversal, which we can clone.
modifyingM
:: MonadState s m
=> ATraversal s s a b
-> (a -> m b) -> m ()
modifyingM t f = do
s <- get
s' <- cloneTraversal t f s
put s'
That's nice because it only traverses the state once.
Even that is overkill, really. The most natural thing is actually
modifyingM
:: MonadState s m
=> LensLike m s s a b
-> (a -> m b) -> m ()
modifyingM t f = do
s <- get
s' <- t f s
put s'
You can apply that directly to a Traversal, Lens, Iso, or Equality, or use cloneTraversal, cloneLens, cloneIso, or (in lens-4.18 or later) cloneEquality to apply it to the monomorphic variants.
I know the functions are all about composition. For example, if I have an arrow from A to B and an arrow from B to C, composition means I also have an arrow from A to C.
But for (>>=), its type is Monad m => m a -> (a -> m b) -> m b. Why m a is equal to a here?
I was wondering why not Monad m => m a -> (m a -> m b) -> m b? Does this make more sense?
#Sibi's answer is right, it wouldn't make sense or be useful for monads to be defined like the second signature. But related to your question about relation between function composition and monadic composition, there is an alternative way of looking at the operator.
Monads have a bunch of alternative constructions equivalent to the bind/return formulation. One of them is in terms of an operator (<=<) called the Kleisli composition operator that composes monadic operations in a structurally similar way to how functions compose.
Arrows:
Functions : a -> b
Monadic operations : a -> m b
Composition:
-- Function composition
(.) :: (b -> c) -> (a -> b) -> a -> c
f . g = \x -> g (f x)
-- Monad composition
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
f <=< g ≡ \x -> g x >>= f
Gabriel Gonzalez wrote a nice blog post about this pattern: http://www.haskellforall.com/2012/08/the-category-design-pattern.html
Try to implement that function yourself and you will find that it would be useless:
func :: Monad m => m a -> (m a -> m b) -> m b
func x f = f x
So what you are basically suggesting is applying a value to a function. I don't think we need a special function for that. :-) The whole point of >>= is that it executes the side effect of it's first parameter and then passes the resultant value of it to the function.
>>= does not correspond to composition, it corresponds to (flipped) application. The flipped version =<< makes this clear:
($) :: (a -> b) -> a -> b
(=<<) :: (Monad m) => (a -> m b) -> m a -> m b
($) takes a unary function and applies it to a value, giving a value; =<< takes a unary action and applies it to the result of a nullary action, giving a nullary action.
The operators corresponding to composition are <=< and >=> from Control.Monad:
(.) :: (b -> c) -> (a -> b) -> a -> c
(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> a -> m c
(.) composes two unary functions, giving a unary function; <=< composes two unary actions, giving a unary action.
If you reorder the type signature, it would make a lot more sense to you....
Let modify be (>>=) with flipped order
modify::Monad m => (a -> m b) -> m a -> m b
or, adding implied parentheses
modify::Monad m => (a -> m b) -> (m a -> m b)
Now it is clear what is happening.... We are given a "lopsided" function that can't be placed in a pipeline of fixed data type, and converting it to a function that can.... These functions are nicer to deal with, as you can add and remove them at will to the pipeline, apply N times, even reorder them. (well, for a=b, at least)
The pattern is very common.... a->m b, for instance, could be a function that takes a val, and may or may not return a value or error.
New to Haskell, and am trying to figure out this Monad thing. The monadic bind operator -- >>= -- has a very peculiar type signature:
(>>=) :: Monad m => m a -> (a -> m b) -> m b
To simplify, let's substitute Maybe for m:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
However, note that the definition could have been written in three different ways:
(>>=) :: Maybe a -> (Maybe a -> Maybe b) -> Maybe b
(>>=) :: Maybe a -> ( a -> Maybe b) -> Maybe b
(>>=) :: Maybe a -> ( a -> b) -> Maybe b
Of the three the one in the centre is the most asymmetric. However, I understand that the first one is kinda meaningless if we want to avoid (what LYAH calls boilerplate code). However, of the next two, I would prefer the last one. For Maybe, this would look like:
When this is defined as:
(>>=) :: Maybe a -> (a -> b) -> Maybe b
instance Monad Maybe where
Nothing >>= f = Nothing
(Just x) >>= f = return $ f x
Here, a -> b is an ordinary function. Also, I don't immediately see anything unsafe, because Nothing catches the exception before the function application, so the a -> b function will not be called unless a Just a is obtained.
So maybe there is something that isn't apparent to me which has caused the (>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b definition to be preferred over the much simpler (>>=) :: Maybe a -> (a -> b) -> Maybe b definition? Is there some inherent problem associated with the (what I think is a) simpler definition?
It's much more symmetric if you think in terms the following derived function (from Control.Monad):
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> (a -> m c)
(f >=> g) x = f x >>= g
The reason this function is significant is that it obeys three useful equations:
-- Associativity
(f >=> g) >=> h = f >=> (g >=> h)
-- Left identity
return >=> f = f
-- Right identity
f >=> return = f
These are category laws and if you translate them to use (>>=) instead of (>=>), you get the three monad laws:
(m >>= g) >>= h = m >>= \x -> (g x >>= h)
return x >>= f = f x
m >>= return = m
So it's really not (>>=) that is the elegant operator but rather (>=>) is the symmetric operator you are looking for. However, the reason we usually think in terms of (>>=) is because that is what do notation desugars to.
Let us consider one of the common uses of the Maybe monad: handling errors. Say I wanted to divide two numbers safely. I could write this function:
safeDiv :: Int -> Int -> Maybe Int
safeDiv _ 0 = Nothing
safeDiv n d = n `div` d
Then with the standard Maybe monad, I could do something like this:
foo :: Int -> Int -> Maybe Int
foo a b = do
c <- safeDiv 1000 b
d <- safeDiv a c -- These last two lines could be combined.
return d -- I am not doing so for clarity.
Note that at each step, safeDiv can fail, but at both steps, safeDiv takes Ints, not Maybe Ints. If >>= had this signature:
(>>=) :: Maybe a -> (a -> b) -> Maybe b
You could compose functions together, then give it either a Nothing or a Just, and either it would unwrap the Just, go through the whole pipeline, and re-wrap it in Just, or it would just pass the Nothing through essentially untouched. That might be useful, but it's not a monad. For it to be of any use, we have to be able to fail in the middle, and that's what this signature gives us:
(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
By the way, something with the signature you devised does exist:
flip fmap :: Maybe a -> (a -> b) -> Maybe b
The more complicated function with a -> Maybe b is the more generic and more useful one and can be used to implement the simple one. That doesn't work the other way around.
You can build a a -> Maybe b function from a function f :: a -> b:
f' :: a -> Maybe b
f' x = Just (f x)
Or, in terms of return (which is Just for Maybe):
f' = return . f
The other way around is not necessarily possible. If you have a function g :: a -> Maybe b and want to use it with the "simple" bind, you would have to convert it into a function a -> b first. But this doesn't usually work, because g might return Nothing where the a -> b function needs to return a b value.
So generally the "simple" bind can be implemented in terms of the "complicated" one, but not the other way around. Additionally, the complicated bind is often useful and not having it would make many things impossible. So by using the more generic bind monads are applicable to more situations.
The problem with the alternative type signature for (>>=) is that it only accidently works for the Maybe monad, if you try it out with another monad (i.e. List monad) you'll see it breaks down at the type of b for the general case. The signature you provided doesn't describe a monadic bind and the monad laws can't don't hold with that definition.
import Prelude hiding (Monad, return)
-- assume monad was defined like this
class Monad m where
(>>=) :: m a -> (a -> b) -> m b
return :: a -> m a
instance Monad Maybe where
Nothing >>= f = Nothing
(Just x) >>= f = return $ f x
instance Monad [] where
m >>= f = concat (map f m)
return x = [x]
Fails with the type error:
Couldn't match type `b' with `[b]'
`b' is a rigid type variable bound by
the type signature for >>= :: [a] -> (a -> b) -> [b]
at monadfail.hs:12:3
Expected type: a -> [b]
Actual type: a -> b
In the first argument of `map', namely `f'
In the first argument of `concat', namely `(map f m)'
In the expression: concat (map f m)
The thing that makes a monad a monad is how 'join' works. Recall that join has the type:
join :: m (m a) -> m a
What 'join' does is "interpret" a monad action that returns a monad action in terms of a monad action. So, you can think of it peeling away a layer of the monad (or better yet, pulling the stuff in the inner layer out into the outer layer). This means that the 'm''s form a "stack", in the sense of a "call stack". Each 'm' represents a context, and 'join' lets us join contexts together, in order.
So, what does this have to do with bind? Recall:
(>>=) :: m a -> (a -> m b) -> m b
And now consider that for f :: a -> m b, and ma :: m a:
fmap f ma :: m (m b)
That is, the result of applying f directly to the a in ma is an (m (m b)). We can apply join to this, to get an m b. In short,
ma >>= f = join (fmap f ma)
At different questions I've found hints in comments concerning using the (->) instance of Monads e.g. for realizing point-free style.
As for me, this is a little too abstract. Ok, I've seen Arrow instances on (->) and it seems to me, that (->) can be used in instance notations but not in type declarations (that would alone be stuff for another question).
Has anyone examples using (->) as instance of Monad? Or a good link?
Sorry if this question may already have been discussed here, but searching for "(->) Monad instance" gives you many many hits as you can imagine ... since nearly every question about Haskell somewhere involves (->) or "Monad".
For a given type r, the function of type r -> a can be thought of as a computation delivering an a using an environment typed r. Given two functions r -> a and a -> (r -> b), it's easy to imagine that one can compose these when given an environment (again, of type r).
But wait! That's exactly what monads are about!
So we can create an instance of Monad for (->) r that implements f >>= g by passing the r to both f and g. This is what the Monad instance for (->) r does.
To actually access the environment, you can use id :: r -> r, which you can now think of as a computation running in an environment r and delivering an r. To create local sub-environments, you can use the following:
inLocalEnvironment :: (r -> r) -> (r -> a) -> (r -> a)
inLocalEnvironment xform f = \env -> f (xform env)
This pattern of having an environment passed to computations that can then query it and modify it locally is useful for not just the (->) r monad, which is why it is abstracted into the MonadReader class, using much more sensible names than what I've used here:
http://hackage.haskell.org/packages/archive/mtl/2.0.1.0/doc/html/Control-Monad-Reader-Class.html
Basically, it has two instances: (->) r that we've seen here, and ReaderT r m, which is just a newtype wrapper around r -> m a, so it's the same thing as the (->) r monad I've described here, except it delivers computations in some other, transformed monad.
To define a monad for (->) r, we need two operations, return and (>>=), subject to three laws:
instance Monad ((->) r) where
If we look at the signature of return for (->) r
return :: a -> r -> a
we can see its just the constant function, which ignores its second argument.
return a r = a
Or alternately,
return = const
To build (>>=), if we specialize its type signature with the monad (->) r,
(>>=) :: (r -> a) -> (a -> r -> b) -> r -> b
there is really only one possible definition.
(>>=) x y z = y (x z) z
Using this monad is like passing along an extra argument r to every function. You might use this for configuration, or to pass options way down deep into the bowels of your program.
We can check that it is a monad, by verifying the three monad laws:
1. return a >>= f = f a
return a >>= f
= (\b -> a) >>= f -- by definition of return
= (\x y z -> y (x z) z) (\b -> a) f -- by definition of (>>=)
= (\y z -> y ((\b -> a) z) z) f -- beta reduction
= (\z -> f ((\b -> a) z) z) -- beta reduction
= (\z -> f a z) -- beta reduction
= f a -- eta reduction
2. m >>= return = m
m >>= return
= (\x y z -> y (x z) z) m return -- definition of (>>=)
= (\y z -> y (m z) z) return -- beta reduction
= (\z -> return (m z) z) -- beta reduction
= (\z -> const (m z) z) -- definition of return
= (\z -> m z) -- definition of const
= m -- eta reduction
The final monad law:
3. (m >>= f) >>= g ≡ m >>= (\x -> f x >>= g)
follows by similar, easy equational reasoning.
We can define a number of other classes for ((->) r) as well, such as Functor,
instance Functor ((->) r) where
and if we look at the signature of
-- fmap :: (a -> b) -> (r -> a) -> r -> b
we can see that its just composition!
fmap = (.)
Similarly we can make an instance of Applicative
instance Applicative ((->) r) where
-- pure :: a -> r -> a
pure = const
-- (<*>) :: (r -> a -> b) -> (r -> a) -> r -> b
(<*>) g f r = g r (f r)
What is nice about having these instances is they let you employ all of the Monad and Applicative combinators when manipulating functions.
There are plenty of instances of classes involving (->), for instance, you could hand-write the instance of Monoid for (b -> a), given a Monoid on a as:
enter code here
instance Monoid a => Monoid (b -> a) where
-- mempty :: Monoid a => b -> a
mempty _ = mempty
-- mappend :: Monoid a => (b -> a) -> (b -> a) -> b -> a
mappend f g b = f b `mappend` g b
but given the Monad/Applicative instance, you can also define this instance with
instance Monoid a => Monoid (r -> a) where
mempty = pure mempty
mappend = liftA2 mappend
using the Applicative instance for (->) r or with
instance Monoid a => Monoid (r -> a) where
mempty = return mempty
mappend = liftM2 mappend
using the Monad instance for (->) r.
Here the savings are minimal, but, for instance the #pl tool for generating point-free code, which is provided by lambdabot on the #haskell IRC channel abuses these instances quite a bit.