In "Learn You a Haskell for Great Good!" author claims that Applicative IO instance is implemented like this:
instance Applicative IO where
pure = return
a <*> b = do
f <- a
x <- b
return (f x)
I might be wrong, but it seems that both return, and do-specific constructs (some sugared binds (>>=) ) comes from Monad IO. Assuming that's correct, my actual question is:
Why Applicative IO implementation depends on Monad IO functions/combinators?
Isn't Applicative less powerfull concept than Monad?
Edit (some clarifications):
This implementation is against my intuition, because according to Typeclassopedia article it's required for a given type to be Applicative before it can be made Monad (or it should be in theory).
(...) according to Typeclassopedia article it's required for a given type to be Applicative before it can be made Monad (or it should be in theory).
Yes, your parenthetical aside is exactly the issue here. In theory, any Monad should also be an Applicative, but this is not actually required, for historical reasons (i.e., because Monad has been around longer). This is not the only peculiarity of Monad, either.
Consider the actual definitions of the relevant type classes, taken from the base package's source on Hackage.
Here's Applicative:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
...about which we can observe the following:
The context is correct given currently existing type classes, i.e., it requires Functor.
It's defined in terms of function application, rather than in (possibly more natural from a mathematical standpoint) terms of lifting tuples.
It includes technically superfluous operators equivalent to lifting constant functions.
Meanwhile, here's Monad:
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
...about which we can observe the following:
The context not only ignores Applicative, but also Functor, both of which are logically implied by Monad but not explicitly required.
It's also defined in terms of function application, rather than the more mathematically natural definition using return and join.
It includes a technically superfluous operator equivalent to lifting a constant function.
It also includes fail which doesn't really fit in at all.
In general, the ways that the Monad type class differs from the mathematical concept it's based on can be traced back through its history as an abstraction for programming. Some, like the function application bias it shares with Applicative, are a reflection of existing in a functional language; others, like fail or the lack of an appropriate class context, are historical accidents more than anything else.
What it all comes down to is that having an instance of Monad implies an instance for Applicative, which in turn implies an instance for Functor. A class context merely formalizes this explicitly; it remains true regardless. As it stands, given a Monad instance, both Functor and Applicative can be defined in a completely generic way. Applicative is "less powerful" than Monad in exactly the same sense that it is more general: Any Monad is automatically Applicative if you copy+paste the generalized instance, but there exist Applicative instances which cannot be defined as a Monad.
A class context, like Functor f => Applicative f says two things: That the latter implies the former, and that a definition must exist to fulfill that implication. In many cases, defining the latter implicitly defines the former anyway, but the compiler cannot deduce that in general, and thus requires both instances to be written out explicitly. The same thing can be observed with Eq and Ord--the latter obviously implies the former, but you still need to define an Eq instance in order to define one for Ord.
The IO type is abstract in Haskell, so if you want to implement a general Applicative for IO you have to do it with the operations that are supported by IO. Since you can implement Applicative in terms of the Monad operations that seems like a good choice. Can you think of another way to implement it?
And yes, Applicative is in some sense less powerful than Monad.
Isn't Applicative a less powerful concept than Monad?
Yes, and therefore whenever you have a Monad you can always make it an Applicative. You could replace IO with any other monad in your example and it would be a valid Applicative instance.
As an analogy, while a color printer may be considered more powerful than a grayscale printer, you can still use one to print a grayscale image.
Of course, one could also base a Monad instance on an Applicative and set return = pure, but you won't be able to define >>= generally. This is what Monad being more powerful means.
In a perfect world every Monad would be an Applicative (so we had class Applicative a => Monad a where ...), but for historical reasons both type classes are independend. So your observation that this definition is kind of "backwards" (using the more powerful abstaction to implement the less powerful one) is correct.
You already have perfectly good answers for older versions of GHC, but in the latest version you actually do have class Applicative m => Monad m so your question needs another answer.
In terms of GHC implementation: GHC just checks what instances are defined for a given type before it tries to compile any of them.
In terms of code semantics: class Applicative m => Monad m doesn't mean the Applicative instance has to be defined "first", just that if it hasn't been defined by the end of your program then the compiler will abort.
Related
From LYAH I understand that the do notation is just syntactic sugar for monadic style; and from the wikibook I read more or less the same; so my understanding is that there can't be any do notation if there's no Monad instance.
Yet I read this definition of the Functor instance of the IO type ctor.
instance Functor IO where
fmap f action = do
result <- action
return (f result)
which is just syntactic sugar for the following, isn't it?
instance Functor IO where
fmap f action = action >>= return . f
which implies the underling assumption the IO is instance of Monad first; and this come against that fact that every Monad is a Functor and not the other way around.
In fact, I had absorbed that a Monad is "something more than" an Applicative, which is in turn "something more than" a Functor, which goes together with Applicative's definition enforcing the Functor constraint on its instances (and Monad's definition ideally requiring that its instances are Applicatives, as in don't make it a Monad if it's not an Applicative).
In other words, the code above makes me think that there would be no way to write the Functor instance for IO, if IO was not a Monad in the first place.
And now that I think about it, maybe this is just like saying that IO was created as a full-fledged Monad, and the instance above was later made just for completeness and mathematical consistency.
But I'm confused, and so I seek for help here.
A type having an instance of Monad implies it must have a definition of Functor (and Applicative), but that doesn’t mean the Functor instance must be defined “first”, only that both instances must exist. As long as the method implementations aren’t defined in terms of each other circularly, there’s no problem.
In fact, it often makes sense to implement Monad for a type first, then define Applicative and Functor mechanically in terms of Monad operations, because Monad is more powerful, so the other instances are just restrictions of the Monad instance:
-- These work for any T with a Monad instance.
instance Functor T where
fmap f x = do
x' <- x
return (f x')
instance Applicative T where
pure = return
f <*> x = do
f' <- f
x' <- x
return (f' x')
This is precisely because “a Monad is ‘something more than’ an Applicative, which is in turn ‘something more than’ a Functor”.
It’s also worth noting that originally, the Monad and Functor classes were unrelated, and the Applicative class (added later) was as well. There were separate equivalent functions for each, like fmap, liftA, and liftM; pure and return; (<*>) and ap; traverse and mapM. Conventionally you would write a Monad instance and implement the other classes in terms of that. These separate definitions still exist, but are now redundant: since the “Applicative–Monad Proposal” made Applicative a superclass of Monad, and Functor of Applicative, you can always use e.g. pure instead of return or traverse instead of mapM, since they’re the same functions, but work in strictly more contexts. So there’s also some historical context as to why there might be separate definitions of these instances for a type.
As #dfeuer points out, there are some data structures where mapM (mapM_, forM, forM_) is more efficient than traverse (resp. traverse_, for, for_), such as Data.Vector types. In the specific case of vectors, I believe this is because the library can take advantage of monadic sequencing as an optimisation, to enable more streaming and allocating results in place. But they are equivalent, in that traverse should always produce the same result.
This question already has answers here:
Is there a monad that doesn't have a corresponding monad transformer (except IO)?
(4 answers)
Closed 4 years ago.
Monad transformers are known for all standard monads (Reader, Writer, State, Cont, List, etc.), but each of these monad transformers works in a slightly different way. There is no general method or formula for constructing a monad transformer given a definition of a type constructor with a monad instance. So, it is not assured that a monad data type designed according to some arbitrary business requirements will have a monad transformer. Is there such an explicit example?
Related work
Another question explains that a functor composition of two monads is not necessarily a monad. See also this question. Those examples do not answer the present question - they merely illustrate the problem of having no general method for constructing a monad transformer. Those examples show that, given two monads M and N, we will sometimes find that M (N a) is a monad, sometimes that N (M a) is a monad, and sometimes neither will be a monad. But this shows neither how to construct a monad transformer for M or N, nor whether it exists at all.
An answer to another question argues that the IO monad cannot have a monad transformer because if it had one IOT, we could apply IOT to List, and then lifting an empty list (lift []) into the resulting monad would have to undo the side effects performed "earlier" by the IO monad. This argument is based on the idea that the IO monad "actually performs" side effects that, presumably, cannot be undone. However, the IO monad is not an explicit type constructor.
Discussion
In every example where a monad type is given explicitly, a monad transformer could be found somehow, - sometimes with certain ingenuity required. For example, the ListT transformer that existed in the Haskell library was relatively recently found to be incorrect in a subtle way, but the problem was eventually fixed by changing the definition of ListT.
Standard examples of monads without transformers are monads such as IO, which is actually not defined by an explicit type constructor - IO is an opaque "magic" type defined by the library somehow, at low level. It seems clear that one cannot define IO as an explicit type constructor, with a monad instance given by pure functions. The IO example shows that a monad transformer may fail to exist if we allow the monad instance to contain hidden low-level code with impure side effects. So, let us limit our attention to monads implemented using pure functions.
There does not seem to be an algorithm that would derive monad transformers automatically from the monad's source code. Do we even know that this is always possible?
To make it more clear what I mean by an "explicit example" of a monad: Suppose I claim that
type Q u v a = ((u -> (a, Maybe a)) -> v) -> u -> (a, Maybe a)
can have a lawful Monad instance with respect to the type parameter a, and I produce the source code for an implementation of the Monad instance for Q u v as pure functions return and join. Do we then know that Q u v has a monad transformer QT u v such that QT u v Id is equivalent to Q u v, and the laws of the monad transformers hold? Do we then know how to construct QT explicitly? I don't.
To decide this question, we need either
to demonstrate an algorithm that would find a monad transformer from an arbitrary given type constructor and a given implementation of a monad instance; e.g. given the code type F a = r -> Either (a, a) (a, a, Maybe a) and an implementation of a monad instance for this, to find the code for the monad transformer; let's limit ourselves to type constructors made out of any combination of ->, tuple, and Either for simplicity; or
to demonstrate a counterexample: an explicit monad type constructor, given by an explicit code definition, e.g. type F a = r -> Either (a, a, a) (a, a, Maybe a) or whatever, such that this is a lawful Monad, with a Monad instance given by pure functions, but we can prove that F has no monad transformer.
This isn't an answer, but it's way too big for a comment. We can write
{-# LANGUAGE GeneralizedNewtypeDeriving
, DeriveFunctor #-}
import Control.Monad.Free
-- All the IO primops you could ever need
data IOF a = PutStrLn String a
| GetLine (String -> a)
deriving Functor
newtype MyIO a = MyIO {unMyIO :: Free IOF a}
deriving (Functor, Applicative, Monad)
But we can actually make a monad transformer out of this:
import Control.Monad.Trans.Free
newtype IOT m a = IOT {unIOT :: FreeT IOF m a}
deriving (Functor, Applicative, Monad, MonadTrans)
So I don't really think even IO is excluded, although the isomorphism in that case is not "internal".
It seems like there are a lot of functions that do the same thing, particularly relating to Monads, Functors, and Applicatives.
Examples (from most to least generic):
fmap == liftA == liftM
(<*>) == ap
liftA[2345] == liftM[2345]
pure == return
(*>) == (>>)
An example not directly based on the FAM class tree:
fmap == map
(I thought there were quite a few more with List, Foldable, Traversable, but it looks like most were made more generic some time ago, as I only see the old, less generic type signatures in old stack overflow / message board questions)
I personally find this annoying, as it means that if I need to do x, and some function such as liftM allows me to do x, then I will have made my function less generic than it could have been, and I am only going to notice that kind of thing by thoroughly reasoning about the differences between types (such as FAM, or perhaps List, Foldable, Traversable combinations as well), which is not beginner friendly at all, as while simply using those types isn't all that hard, reasoning about their properties and laws requires a lot more mental effort.
I am guessing a lot of these equivalencies come from the Applicative Monad Proposal. If that is the reason for them (and not some other reason I am missing for having less generic functions available for confusion), are they going to be deprecated / deleted ever? I can understand waiting a long time to delete them, due to breaking existing code, but surely deprecation is a good idea?
The short answers are "history" and "regularity".
Originally "map" was defined for lists. Then type-classes were introduced, with the Functor type class, so the generalised version of "map" for any functor had to be called something different, otherwise existing code would be broken. Hence "fmap".
Then monads came along. Instances of monads did not need to be functors, so "liftM" was created, along with "liftM2", "liftM3" etc. Of course if a type is an instance of both Monad and Functor then fmap = liftM.
Monads also have "ap", used in expressions like f `ap` arg1 `ap` arg2. This was very handy, but then Applicative Functors were added. (<*>) did the same job for applicative functors as 'ap', but because many applicative functors are not monads it had to be called something different. Likewise liftAx versus liftMx and "pure" versus "return".
They aren't equivalent though. equivalent things in haskell can be interchanged with no difference at all in functionality. Consider for example pure and return
EDIT: I wrote some examples down, but they were really bad since they involved Maybe a, a type that is both an applicative and a monad, so the functions could be used pretty interchangeably.
There are types that are applicatives but not monads though (see this question for examples), and by studying the type of the following expression, we can see that this could lead to some roadbumps:
pure 1 >>= pure :: (Monad m, Num b) => m b
I personally find this annoying, as it means that if I need to do x, and some function such as liftM allows me to do x, then I will have made my function less generic than it could have been
This logic is backwards.
Normally you know in advance the type of the thing you want to write, be it IO String or (Foldable f, Monoid t, Monad m) => f (m t) -> m t or whatever. Let's take the first case, getLineCapitalized :: IO String. You could write it as
getLineCapitalized = liftM (map toUpper) getLine
or
getLineCapitalized = fmap (fmap toUpper) getLine
Is the former "less generic" because it uses the specialized functions liftM and map? Of course not. This is intrinsically an IO action that produces a list. It cannot become "more generic" by changing it to the second version since those fmaps will have their types fixed to IO and [] anyways. So, there is no advantage to the second version.
By writing the first version, you provide contextual information to the reader for free. In liftM (map foo) bar, the reader knows that bar is going to be an action in some monad that returns a list. In fmap (fmap foo) bar, it could be any sort of doubly-nested structure whatsoever. If bar is something complicated rather than just getLine, then this kind of information is helpful for understanding more easily what is going on in bar.
In general, you should write a function in two steps.
Decide what the type of the function should be. Make it as general or as specific as you want. The more general the type of the function, the stronger guarantees you get on its behavior from parametricity.
Once you have decided on the type of your function, implement it using the most specific available functions. By doing so, you are providing the most information to the reader of your function. You never lose any generality or parametricity guarantees by doing so, since those only depend on the type, which you already determined in step 1.
Edit in response to comments: I was reminded of the biggest reason to use the most specific function available, which is catching bugs. The type length :: [a] -> Int is essentially the entire reason that I still use GHC 7.8. It's never happened that I wanted to take the length of an unknown Foldable structure. On the other hand, I definitely do not want to ever accidentally take the length of a pair, or take the length of foo bar baz which I think has type [a], but actually has type Maybe [a].
In the use cases for Foldable that are not already covered by the rest of the Haskell standard, lens is a vastly more powerful alternative. If I want the "length" of a Maybe t, lengthOf _Just :: Maybe t -> Int expresses my intent clearly, and the compiler can check that the program actually matches my intent; and I can go on to write lengthOf _Nothing, lengthOf _Left, etc. Explicit is better than implicit.
There are some "redundant" functions like liftM, ap, and liftA that have a very real use and taking them out would cause loss of functionality --- you can use liftM, ap, and liftA to implement your Functor or Applicative instances if all you've written is a Monad instance. It lets you be lazy and do, say:
instance Monad Foo where
return = ...
(>>=) = ...
Now you've done all of the rewarding work of defining a Monad instance, but this won't compile. Why? Because you also need a Functor and Applicative instance.
So, because you're quickly prototyping, or lazy, or can't think of a better way, you can just get a free Functor and Applicative instance:
instance Functor Foo where
fmap = liftM
instance Applicative Foo where
pure = return
(<*>) = ap
In fact, you can just copy-and-paste that chunk of code everywhere you need to quickly define a Functor or Applicative instance when you already have a Monad instance defined.
The same goes for fmapDefault from Data.Traversable. If you've implemented Traversable, you can also implement Foldable and Functor:
instance Functor Bar where
fmap = fmapDefault
no extra work required!
There are some redundant functions, however, that really have no actual usage other than being historical accidents from a time when Functor was not a superclass of Monad. These have literally zero use/point in existing...and include things like the liftM2, liftM3 etc., and (>>) and friends.
What is the difference between return and pure from Control.Applicative ? It seems that I can use pure even at the end of a do block?
So is there any situation where one should be preferred over the other (besides that everyone expects a return at the end of a do Block)?
In GHC 7.8 and before, Applicative was not a superclass of Monad. It was even possible for a Monad instance to not have an Applicative instance. There was, however, an expectation that pure and return should have the same behavior for types that are instances of both.
In GHC 7.10, due to the Functor-Applicative-Monad Proposal, Applicative is now a superclass of Monad (class Applicative m => Monad m) and it is now a rule that pure and return must be the same for all Monad instances. In fact, the default implementation of return is now pure, as seen in the source on hackage.
pure might be preferred to return because it does not incur a Monad constraint, only an Applicative constraint, thus making the function more general. return might be preferred to pure in do notation because of historical precedent, but pure could be used to exactly the same effect.
The Applicative typeclass was added after Monad and historically the Monad class has not been a subclass of Applicative. This was changed fairly recently in the Applicative-Monad-Proposal and this means that return a should be equivalent to pure a for every Monad instance.
There is a proposal to move return out of the Monad class and make it an alias for pure.
Therefore when dealing with a Monad you should always be able to use pure instead of return. You cannot go the other way however since pure has a more general type than return since it only returns an Applicative. For example the following
wontCheck :: Applicative f => f Int
wontCheck = return 4
won't type check since return requires f to be a Monad.
To clarify the question: it is about the merits of the monad type class (as opposed to just its instances without the unifying class).
After having read many references (see below),
I came to the conclusion that, actually, the monad class is there to solve only one, but big and crucial, problem: the 'chaining' of functions on types with context. Hence, the famous sentence "monads are programmable semicolons".
In fact, a monad can be viewed as an array of functions with helper operations.
I insist on the difference between the monad class, understood as a general interface for other types; and these other types instantiating the class (thus, "monadic types").
I understand that the monad class by itself, only solves the chaining of operators because mainly, it only mandates its type instances
to have bind >>= and return, and tell us how they must behave. And as a bonus, the compiler greatyly helps the coding providing do notation for monadic types.
On the other hand,
it is each individual type instantiating the monad class which solves each concrete problem, but not merely for being a instance of Monad. For instance Maybe solves "how a function returns a value or an error", State solves "how to have functions with global state", IO solves "how to interact with the outside world", and so on. All theses classes encapsulate a value within a context.
But soon or later, we will need to chain operations on such context-types. I.e., we will need to organize calls to functions on these types in a particular sequence (for an example of such a problem, please read the example about multivalued functions in You could have invented monads).
And you get solved the problem of chaining, if you have each type be an instance of the monad class.
For the chaining to work you need >>= just with the exact signature it has, no other. (See this question).
Therefore, I guess that the next time you define a context data type T for solving something, if you need to sequence calls of functions (on values of T) consider making T an instance of Monad (if you need "chaining with choice" and if you can benefit from the do notation). And to make sure you are doing it right, check that T satisfies the monad laws
Then, I ask two questions to the Haskell experts:
A concrete question: is there any other problem that the monad class solves by ifself (leaving apart monadic classes)? If any, then, how it compares in relevance to the problem of chaining operations?
An optional general question: are my conclusions right, am I misunderstanding something?
References
Tutorials
Monads in pictures Definitely worth it; read this one first.
Fistful of monads
You could have invented monads
Monads are trees (pdf)
StackOverflow Questions & Answers
How to detect a monad
On the signature of >>= monad operator
You're definitely on to something in the way that you're stating this—there are many things that Monad means and you've separated them out well.
That said, I would definitely say that chaining operations is not the primary thing solved by Monads. That can be solved using plain Functors (with some trouble) or easily with Applicatives. You need to use the full monad spec when "chaining with choice". In particular, the tension between Applicative and Monad comes from Applicative needing to know the entire structure of the side-effecting computation statically. Monad can change that structure at runtime and thus sacrifices some analyzability for power.
To make the point more clear, the only place you deal with a Monad but not any specific monad is if you're defining something with polymorphism constrained to be a Monad. This shows up repeatedly in the Control.Monad module, so we can examine some examples from there.
sequence :: [m a] -> m [a]
forever :: m a -> m b
foldM :: (a -> b -> m a) -> a -> [b] -> m a
Immediately, we can throw out sequence as being particular to Monad since there's a corresponding function in Data.Traversable, sequenceA which has a type slightly more general than Applicative f => [f a] -> f [a]. This ought to be a clear indicator that Monad isn't the only way to sequence things.
Similarly, we can define foreverA as follows
foreverA :: Applicative f => f a -> f b
foreverA f = flip const <$> f <*> foreverA f
So more ways to sequence non-Monad types. But we run into trouble with foldM
foldM :: (Monad m) => (a -> b -> m a) -> a -> [b] -> m a
foldM _ a [] = return a
foldM f a (x:xs) = f a x >>= \fax -> foldM f fax xs
If we try to translate this definition to Applicative style we might write
foldA :: (Applicative f) => (a -> b -> f a) -> a -> [b] -> f a
foldA _ a [] = pure a
foldA f a (x:xs) = foldA f <$> f a x <*> xs
But Haskell will rightfully complain that this doesn't typecheck--each recursive call to foldA tries to put another "layer" of f on the result. With Monad we could join those layers down, but Applicative is too weak.
So how does this translate to Applicatives restricting us from runtime choices? Well, that's exactly what we express with foldM, a monadic computation (a -> b -> m a) which depends upon its a argument, a result from a prior monadic computation. That kind of thing simply doesn't have any meaning in the more purely sequential world of Applicative.
To solve the problem of chaining operations on an individual monadic type, it's not at all necessary to make it an instance of Monad and be sure the monad laws are satisfied. You could just implement a chaining operation directly on your type.
It would probably be very similar to the monadic bind, but not necessarily exactly the same (recall that bind for lists is concatMap, a function that exists anyway, but with the arguments in a different order). And you wouldn't have to worry about the monad laws, because you would have a slightly different interface for each type, so they wouldn't have any common requirements.
To ask what problem the Monad type class itself solves, look at all the functions (in Control.Monad and else where) that work on values in any monadic type. The problem solved is code reuse! Monad is exactly the part of all the monadic types that is common to each and every one of them. That part is sufficient on its own to write useful computations. All of these functions could be implemented for any individual monadic type (often more directly), but they've already been implemented for all monadic types, even the ones that don't exist yet.
You don't write a Monad instance so that you can chain operations on your type (often you already have a way of chaining, in fact). You write a Monad instance for all the code that automatically comes along with the Monad instance. Monad isn't about solving any problem for any single type, it's about a way of viewing many disparate types as instances of a single unifying concept.