Relationship between Functor, Applicative Functor, and Monad - haskell

When reading up on type classes I have seen that the relationship between Functors, Applicative Functors, and Monads is that of strictly increasing power. Functors are types that can be mapped over. Applicative Functors can do the same things with certain effects. Monads the same with possibly unrestrictive effects. Moreover:
Every Monad is an Applicative Functor
Every Applicative Functor is a Functor
The definition of the Applicative Functor shows this clearly with:
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
But the definition of Monad is:
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
m >> n = m >>= \_ -> n
fail :: String -> m a
According to Brent Yorgey's great typeclassopedia that an alternative definition of monad could be:
class Applicative m => Monad' m where
(>>=) :: m a -> (a -> m b) -> m b
which is obviously simpler and would cement that Functor < Applicative Functor < Monad. So why isn't this the definition? I know applicative functors are new, but according to the 2010 Haskell Report page 80, this hasn't changed. Why is this?

Everyone wants to see Applicative become a superclass of Monad, but it would break so much code (if return is eliminated, every current Monad instance becomes invalid) that everyone wants to hold off until we can extend the language in such a way that avoids breaking the code (see here for one prominent proposal).
Haskell 2010 was a conservative, incremental improvement in general, standardising only a few uncontroversial extensions and breaking compatibility in one area to bring the standard in line with every existing implementation. Indeed, Haskell 2010's libraries don't even include Applicative — less of what people have come to expect from the standard library is standardised than you might expect.
Hopefully we'll see the situation improve soon, but thankfully it's usually only a mild inconvenience (having to write liftM instead of fmap in generic code, etc.).

Changing the definition of Monad at this point, would have broken a lot of existing code (any piece of code that defines a Monad instance) to be worthwhile.
Breaking backwards-compatibility like that is only worthwhile if there is a large practical benefit to the change. In this case the benefit is not that big (and mostly theoretical anyway) and wouldn't justify that amount of breakage.

Related

Why is ap available inside Applicative?

I am trying to implement MonadUnliftIO for Snap and analyzing Snap classes.
I discovered that ap is used for implementing Applicative while ap requires Monad and Monad requires Applicative. It looks like a loop.
I thought till now that is not possible to write such things.
What is the limit for such kind of trick?
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
instance Applicative Snap where
pure x = ...
(<*>) = ap
ap :: Monad m => m (a -> b) -> m a -> m b
This only works because Snap has a Monad instance (and it's actually in scope at that point).
Effectively, the compiler handles declarations in two separate passes: first it resolves all the instance heads
instance Applicative Snap
instance Monad Snap
...without even looking in the actual method implementations. This works out fine: Monad is happy as long as it sees the Applicative instance.
So then it already knows that Snap is a monad. Then it proceeds to typecheck the (<*>) implementation, notices that it requires the Monad instance, and... yeah, it's there, so that too is fine.
The actual reason we have ap :: Monad m => ... is mostly historical: the Haskell98 Monad class did not have Applicative or even Functor as a superclass, so it was possible to write code Monad m => ... that could then not use fmap or <*>. Therefore the liftM and ap functions were introduced as replacement.
Then, when the better current class hierarchy was established, many instances were simply defined by referring back to the already existing Monad instance, which is after all sufficient for everything.
IMO it is usually a good idea to directly implement <*> and definitely fmap before writing the Monad instance, rather than the other way around.
I think you are imagining a cycle like this:
(<*>) is implemented with ap
(>>=) is implemented with (<*>)
ap is implemented using (>>=)
And yes, if you try this, it will indeed give you an infinite loop!
However, this is not what your code block does. Its implementations look more like this:
(>>=) is implemented from first principles, without using any Applicative functions
ap is implemented using (>>=)
(<*>) is implemented in terms of ap
Which is obviously fine — there’s no cycles of any sort in this set of function definitions.
One thing which might still be a bit confusing is: how can you implement an Applicative function in terms of a Monad function, when a type can only be a Monad if it is already Applicative? To answer this, let’s add explicit type signatures to your code sample (note this requires language extensions to compile):
class Functor f => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
class Applicative m => Monad m where
return :: a -> m a
instance Applicative Snap where
pure :: a -> Snap a
pure x = ...
(<*>) :: Snap (a -> b) -> Snap a -> Snap b
(<*>) = ap
ap :: Monad m => m (a -> b) -> m a -> m b
The answer is now clear: we are not in fact defining (<*>) for just any arbitrary Applicative type! Rather, we are defining it for Snap only, which means we can use any function defined to work on Snaps — including those from the Monad typeclass. The fact that this function happens to be within an instance Applicative Snap block doesn’t matter: in all other respects, it’s just an ordinary function definition, and there’s no reason why the full range of Snap functions shouldn’t be able to appear in it.
There should be some instance Monad Snap somewhere else. The ap use in the Applicative instance will make use of >>= from that instance.
In general, an instance for Applicative can not make use of ap in this way, but when then applicative is also a monad, I think it is quite common to do so, since it's convenient.
Note that, if one chooses this route, it should avoid using <*> or ap inside the definition of >>=, since that could lead to infinite recursion.
The fact that the two instances are mutually recursive, in some sense, is not an issue. Haskell allows mutual recursion, and this also reflects on instances. The programmer however must ensure that the recursion actually terminates, or be prepared to have a non-terminating program.

What's a functor on the category of monads?

Note, this question is not about "monoids in the category of endofunctors". Nor is it directly about Functors (a Monad is always a Functor, but this question is concerned mainly about monad transformers)
The docs on Haskell's SelectT monad transformer states that
SelectT is not a functor on the category of monads, and many operations cannot be lifted through it.
What's the category of monads? What are the arrows in that category?
Why are some monad transformers functors on the category of monads (MaybeT, RWST, etc), but some not (ContT, SelectT)?
What good does it do, from a programming perspective, to be a functor on the category of monads? Why should I care as a consumer of the library?
What's the category of monads? What are the arrows in that category?
The category where the objects are monads, i.e., types T of kind Type -> Type with Monad instances, and the arrows A -> B are natural transformations between their underlying functors, conventionally represented in Haskell by functions of type forall x. A x -> B x (although strictly speaking parametricity is a stronger condition than naturality).
There’s an implementation of this in the mmorph package.
The initial object in this category is Identity, since for any monad T there’s exactly one natural transformation forall x. Identity x -> T x. Dually, I think the final object is Const ().
Why are some monad transformers functors on the category of monads (MaybeT, RWST, etc), but some not (ContT, SelectT)?
A functor in this category would need a lifted fmap:
fmap'
:: forall m n. (Monad m, Monad n)
=> (forall x. m x -> n x) -> forall x. T m x -> T n x
And you can’t implement this in general for ContT and SelectT. I’m not sure precisely why, but it seems to depend on variance: we’re trying to implement a covariant functor, but ContT and SelectT are invariant in their underlying monads, e.g., m occurs both positively and negatively in the (a -> m r) -> m r inside a ContT r m a.
What good does it do, from a programming perspective, to be a functor on the category of monads? Why should I care as a consumer of the library?
If you have a general way to “run” a monad m in a monad n, you can’t necessarily lift that into ContT or SelectT; you’re stuck with the more restricted mapping operations like these:
mapSelectT :: (m a -> m a) -> SelectT r m a -> SelectT r m a
mapContT :: (m r -> m r) -> ContT r m a -> ContT r m a
Where the underlying monad and result type are fixed. So you can’t always freely hoist actions within a stack that uses these transformers.

Why does sequenceA need Traversable?

From the Typeclassopedia:
sequence :: Monad m => [m a] -> m [a]
Takes a list of computations and combines them into one computation which collects a list of their results. It is again something of a historical accident that sequence has a Monad constraint, since it can actually be implemented only in terms of Applicative.
And indeed, there is sequenceA which operates on Applicative types.
sequenceA :: (Applicative f, Traversable t) => t (f a) -> f (t a)
But wait, why does sequenceA need the Traversable constraint when it can be implemented without it?
seqA :: Applicative f => [f a] -> f [a]
seqA = foldr fx (pure [])
where
fx f fs = pure (:) <*> f <*> fs)
This is a subject that can be initially confusing because there is a lot of history and change around it, and older explanations are out of date. The history is roughly this:
The idea of the sequence operation dates back to the 1990s, when the Monad class was incorporated into Haskell and people first formulated generic operations for it. The signature that you quote from the Typeclassopedia reflects this: sequence :: Monad m => [m a] -> m [a]. It can work with any monad, but it is hardcoded to work on lists.
The Applicative class was developed during the mid-to-late 2000s; the seminal paper that everybody cites is McBride and Patterson (2008), "Applicative Programming with Effects". McBride and Patterson also note that:
The old monadic sequence operation can in fact be generalized to dist :: Applicative f => [f a] -> f [a]. The Monad constraint is too narrow!
Likewise, the old mapM function (close relative to sequence) generalizes to traverse :: Applicative f => (a -> f b) -> [a] -> f [b].
This can be generalized to non-list data structures by putting these operations into a Traversable class that they propose in the paper.
The Applicative and Traversable classes were added into the GHC base libraries, with some small changes. The dist function was named sequenceA instead, and the Foldable class joined Traversable for types that support only a subset of Traversable's requirements.
These classes proved extremely popular. But that shows that the original sequence :: Monad m => [m a] -> m [a] signature was wrong in hindsight.
So finally, fast-forward to 2015, when GHC implemented the Applicative/Monad Proposal (make Applicative a superclass of Monad) and the Foldable/Traversable Proposal, where the base libraries were revised in order to get them close to the ideal, hindsight-informed design.
The Foldable/Traversable Proposal, however, did not change the signature of sequence. I can't tell you precisely why, but the answer is going to be some obtuse detail that boils down to historical reasons, backward compatibility or something like that. But I can tell you that if we could start all over again:
sequence would have sequenceA's signature;
sequenceA would not exist independently of sequence;
mapM is just traverse with the wrong signature, and thus would not exist independently either.

Are there a thing call "semi-monad" or "counter-monad"?

Well, I am studying Haskell Monads. When I read the Wikibook Category theory article, I found that the signature of monad morphisms looks pretty like tautologies in logic, but you need to convert M a to ~~A, here ~ is the logic negation.
return :: a -> M a -- Map to tautology A => ~~A, double negation introduction
(>>=) :: M a -> (a -> M b) -> M b -- Map to tautology ~~A => (A => ~~B) => ~~B
the other operations is also tautologies:
fmap :: (a -> b) -> M a -> M b -- Map to (A => B) -> (~~A => ~~B)
join :: M (M a) -> M a -- Map to ~~(~~A) => ~~A
It's also understood that according to the fact that the Curry-Howard correspondence of normal functional languages is the intuitive logic, not classical logic, so we cannot expect a tautology like ~~A => A can have a correspondence.
But I am thinking of something else. Why the Monad can only relate to a double negation? what is the correspondence of single negation? This lead me to the following class definition:
class Nomad n where
rfmap :: (a -> b) -> n b -> n a
dneg :: a -> n (n a)
return :: Nomad n => a -> n (n a)
return = dneg
(>>=) :: Nomad n => n (n a) -> (a -> n (n b)) -> n (n b)
x >>= f = rfmap dneg $ rfmap (rfmap f) x
Here I defined a concept called "Nomad", and it supports two operations (both related to a logic axiom in intuitive logic). Notice the name "rfmap" means the fact that its signature is similar to functor's fmap, but the order of a and b are reversed in result. Now I can re-define the Monad operations with them, with replace M a to n (n a).
So now let's go to the question part. The fact that Monad is a concept from category theory seems to mean that my "Nomad" is also a category theory concept. So what is it? Is it useful? Are there any papers or research results exists in this topic?
Double negation is a particular monad
data Void --no constructor because it is uninhabited
newtype DN a = DN {runDN :: (a -> Void) -> Void}
instance Monad DN where
return x = DN $ \f -> f x
m >>= k = DN $ \c -> runDN m (\a -> runDN (k a) c))
actually, this is an example of a more general monad
type DN = Cont Void
newtype Cont r a = Cont {runCont :: (a -> r) -> r}
which is the monad for continuation passing.
A concept like "monad" is not defined just by a signature, but also by some laws. So, here is a question, what should the laws for your construction be?
(a -> b) -> f b -> f a
is the signature of a method well known to category theory, the contravariant functor. It obeys essentially the same laws as functors (preserves (co)composition and identity). Actually, a contravariant functor is exactly a functor to the oppositite category. Since we are interested in "haskell functors" which are supposed to be endo-functors, we can see that a "haskell contravariant functor" is a functor Hask -> Hask_Op.
On the other hand, what about
a -> f (f a)
what laws should this have? I have a suggestion. In category theory, it is possible to map between Functors. Given two functors from F, G each from category C to category D, a natural transformation from F to G is a morphism in D
forall a. F a -> G a
that obeys certain coherence laws. You can do a lot with natural transformations, including using them to define a "functor category." But, the classic joke (due to Mac Lane) is that categories were invented to talk about functors, functors were invented to talk about natural transformations, and natural transformations were invented to talk about adjunctions.
A functor F : D -> C and a functor G : C -> D form an adjunction from C to D if there exist two natural transformations
unit : Id -> G . F
counit : F . G -> Id
This idea of an adjunction is a frequent way of understanding monads. Every adjunction gives rise to a monad in a totally natural way. That is, since the composition of these two functors is an endofunctor, and you have something akin to return (the unit), all you need is the join. But that is easy, join is just a function G . F . G . F -> G . F which you get by just using the counit "in the middle".
So, then with all this, what is it that you are looking for? Well
dneg :: a -> n (n a)
looks exactly like the unit of the adjunction of a contravariant functor with itself. Therefore, your Nomad type is likely (certainly if your use of it to construct a monad is correct) exactly the same as "a contravariant functor which is self adjoint." Searching for self adjoint functors will lead you back to Double-negation and Continuation passing...which is just where we started!
EDIT: Almost certainly some of the arrows above are backwards. The basic idea is right, though. You can work it out yourself using the citations below:
The best books on category theory are probably,
Steve Awodey, Category Theory
Sanders Mac Lane, Categories for the Working Mathematician
although numerous more approachable intro books exist including Benjamin Pierces book on Category Theory for computer scientists.
Video lectures online
The Category Theory lectures by Steve Awodey from the Oregon Programming Language Summer School
The Catsters short lectures on youtube, indexed here, pay particular attention to the videos on adjunctions
A number of papers explore the adjunction angle on the continuation monad, for example
Hayo Thielecke, Continuation Semantics and Self-adjointness
The search terms "self adjoint", "continuation", and "monad" are good. Also, a number of bloggers have written about these issues. If you google "where do monads come from" you get useful results like this one from the n category cafe, or this one from sigfpe. Also Sjoerd Vissche's link to the Comonad reader.
That would be a self-adjoint contravariant functor. rfmap provides the contravariant functor part, and dneg is the unit and counit of the adjunction.
Op r is an example, which creates the continuation monad. See the contravariant modules in http://hackage.haskell.org/package/adjunctions for some code.
You should read http://comonad.com/reader/2011/monads-from-comonads/, which is related and very interesting.

Computation Constructs (Monads, Arrows, etc.)

I have become rather interested in how computation is modeled in Haskell. Several resources have described monads as "composable computation" and arrows as "abstract views of computation". I've never seen monoids, functors or applicative functors described in this way. It seems that they lack the necessary structure.
I find that idea interesting and wonder if there are any other constructs that do something similar. If so, what are some resources that I can use to acquaint myself with them? Are there any packages on Hackage that might come in handy?
Note: This question is similar to
Monads vs. Arrows and https://stackoverflow.com/questions/2395715/resources-for-learning-monads-functors-monoids-arrows-etc, but I am looking for constructs beyond funtors, applicative functors, monads, and arrows.
Edit: I concede that applicative functors should be considered "computational constructs", but I'm really looking for something I haven't come across yet. This includes applicative functors, monads and arrows.
Arrows are generalized by Categories, and so by the Category typeclass.
class Category f where
(.) :: f a b -> f b c -> f a c
id :: f a a
The Arrow typeclass definition has Category as a superclass. Categories (in the haskell sense) generalize functions (you can compose them but not apply them) and so are definitely a "model of computation". Arrow provides a Category with additional structure for working with tuples. So, while Category mirrors something about Haskell's function space, Arrow extends that to something about product types.
Every Monad gives rise to something called a "Kleisli Category" and this construction gives you instances of ArrowApply. You can build a Monad out of any ArrowApply such that going full circle doesn't change your behavior, so in some deep sense Monad and ArrowApply are the same thing.
newtype Kleisli m a b = Kleisli { runKleisli :: a -> m b }
instance Monad m => Category (Kleisli m) where
id = Kleisli return
(Kleisli f) . (Kleisli g) = Kleisli (\b -> g b >>= f)
instance Monad m => Arrow (Kleisli m) where
arr f = Kleisli (return . f)
first (Kleisli f) = Kleisli (\ ~(b,d) -> f b >>= \c -> return (c,d))
second (Kleisli f) = Kleisli (\ ~(d,b) -> f b >>= \c -> return (d,c))
Actually every Arrow gives rise to an Applicative (universally quantified to get the kinds right) in addition to the Category superclass, and I believe the combination of the appropriate Category and Applicative is enough to reconstruct your Arrow.
So, these structures are deeply connected.
Warning: wishy-washy commentary ahead. One central difference between the Functor/Applicative/Monad way of thinking and the Category/Arrow way of thinking is that while Functor and its ilk are generalizations at the level of object (types in Haskell), Category/Arrow are generelazation of the notion of morphism (functions in Haskell). My belief is that thinking at the level of generalized morphism involves a higher level of abstraction than thinking at the level of generalized objects. Sometimes that is a good thing, other times it is not. On the other-hand, despite the fact that Arrows have a categorical basis, and no one in math thinks Applicative is interesting, it is my understanding that Applicative is generally better understood than Arrow.
Basically you can think of "Category < Arrow < ArrowApply" and "Functor < Applicative < Monad" such that "Category ~ Functor", "Arrow ~ Applicative" and "ArrowApply ~ Monad".
More Concrete Below:
As for other structures to model computation: one can often reverse the direction of the "arrows" (just meaning morphisms here) in categorical constructions to get the "dual" or "co-construction". So, if a monad is defined as
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
(okay, I know that isn't how Haskell defines things, but ma >>= f = join $ fmap f ma and join x = x >>= id so it just as well could be)
then the comonad is
class Functor m => Comonad m where
extract :: m a -> a -- this is co-return
duplicate :: m a -> m (m a) -- this is co-join
This thing turns out to be pretty common also. It turns out that Comonad is the basic underlying structure of cellular automata. For completness, I should point out that Edward Kmett's Control.Comonad puts duplicate in a class between functor and Comonad for "Extendable Functors" because you can also define
extend :: (m a -> b) -> m a -> m b -- Looks familiar? this is just the dual of >>=
extend f = fmap f . duplicate
--this is enough
duplicate = extend id
It turns out that all Monads are also "Extendable"
monadDuplicate :: Monad m => m a -> m (m a)
monadDuplicate = return
while all Comonads are "Joinable"
comonadJoin :: Comonad m => m (m a) -> m a
comonadJoin = extract
so these structures are very close together.
All Monads are Arrows (Monad is isomorphic to ArrowApply). In a different way, all Monads are instances of Applicative, where <*> is Control.Monad.ap and *> is >>. Applicative is weaker because it does not guarantee the >>= operation. Thus Applicative captures computations that do not examine previous results and branch on values. In retrospect much monadic code is actually applicative, and with a clean rewrite this would happen.
Extending monads, with recent Constraint kinds in GHC 7.4.1 there can now be nicer designs for restricted monads. And there are also people looking at parameterized monads, and of course I include a link to something by Oleg.
In libraries these structures give rise to different type of computations.
For example Applicatives can be used to implement static effects. With that I mean effects, which are defined at forehand. For example when implementing a state machine, rejecting or accepting an input state. They can't be used to manipulate their internal structure in terms of their input.
The type says it all:
<*> :: f (a -> b) -> f a -> f b
It is easy to reason, the structure of f cannot be depend om the input of a. Because a cannot reach f on the type level.
Monads can be used for dynamic effects. This also can be reasoned from the type signature:
>>= :: m a -> (a -> m b) -> m b
How can you see this? Because a is on the same "level" as m. Mathematically it is a two stage process. Bind is a composition of two function: fmap and join. First we use fmap together with the monadic action to create a new structure embedded in the old one:
fmap :: (a -> b) -> m a -> m b
f :: (a -> m b)
m :: m a
fmap f :: m a -> m (m b)
fmap f m :: m (m b)
Fmap can create a new structure, based on the input value. Then we collapse the structure with join, thus we are able to manipulate the structure from within the monadic computation in a way that depends on the input:
join :: m (m a) -> m a
join (fmap f m) :: m b
Many monads are easier to implement with join:
(>>=) = join . fmap
This is possible with monads:
addCounter :: Int -> m Int ()
But not with applicatives, but applicatives (and any monad) can do things like:
addOne :: m Int ()
Arrows give more control over the input and the output types, but for me they really feel similar to applicatives. Maybe I am wrong about that.

Resources