I was working on the following small fragment of code:
import Control.Monad
import Data.Aeson
import qualified Data.HashMap.Strict as HashMap
import Data.Map (Map)
import qualified Data.Map as Map
import GHC.Generics
-- definitions of Whitelisted, WhitelistComment and their FromJSON instances
-- omitted for brevity
data Whitelist = Whitelist
{ whitelist :: Map Whitelisted WhitelistComment
} deriving (Eq, Ord, Show)
instance FromJSON Whitelist where
parseJSON (Object v) =
fmap (Whitelist . Map.fromList) . forM (HashMap.toList v) $ \(a, b) -> do
a' <- parseJSON (String a)
b' <- parseJSON b
return (a', b')
parseJSON _ = mzero
when I realised that I can rewrite the do block in applicative style:
instance FromJSON Whitelist where
parseJSON (Object v) =
fmap (Whitelist . Map.fromList) . forM (HashMap.toList v) $ \(a, b) ->
(,) <$> parseJSON (String a) <*> parseJSON b
parseJSON _ = mzero
and with that I could also replace forM with for. Before making the change above I switched to for first:
instance FromJSON Whitelist where
parseJSON (Object v) =
fmap (Whitelist . Map.fromList) . for (HashMap.toList v) $ \(a, b) -> do
a' <- parseJSON (String a)
b' <- parseJSON b
return (a', b')
parseJSON _ = mzero
and to my surprise this still compiled. Given the definition of for:
for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b)
I thought the Applicative constraint would prevent me from using do notation / return in the action passed to for.
I'm clearly missing something fundamental here, either in terms of what for signature really implies, or how the code I posted is interpreted by the compiler, and would appreciate any help understanding what's going on.
This is just the usual caller-vs-implementer duality going on, where one side gets flexibility and the other restriction.
for provides you with this interface:
for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b)
You as the caller get the flexibility to choose any type f to instantiate it, so you can use it as if it were:
for :: Traversable t => t a -> (a -> Parser b) -> Parser (t b)
Clearly once you've done that, there's no reason you couldn't use any Parser-specific functionality in the function you pass to for, including Monad stuff.
The implementer of for on the other hand gets restricted by the polymorphism in the interface of for. They have to work with any choice of f, so they can only use the Applicative interface in the code they write to implement for. But that only restricts the code of for itself, not the function passed into it.
If the author of for wanted to restrict what the caller could do in that function, they could have used RankNTypes to instead provide this interface:
for :: forall t f. (Traversable t, Applicative f) => t a -> (forall g. Applicative g => a -> g b) -> f (t b)
Now the provided lambda itself must be polymorphic in g (subject to an Applicative constraint). The caller of for still gets the flexibility to choose f, with the implementer being restricted in using only Applicative features. But the caller of for is the implementer of the function argument, so now that that function is polymorphic itself the caller of for is restricted to using only Applicative features there and the implementer of for gets the freedom to use it with any type they like (including possibly using monad features to combine it with other internal values). With this specific type signature the implementer of for will have to choose to instantiate g with the same type the caller of for selected for f, in order to come up with the final f (t b) return value. But the caller of for would still be restricted by the type system to providing a function that works for any Applicative g.
The point is, if you get to choose what type to instantiate a polymorphic signature with then you are not the one restricted by that interface. You can choose a type and then use whatever other features of that type you like, provided you still do provide the bits of information the interface requires of you. i.e. You can use non-Traversable functionality to create your t a and non-Applicative functionality to create your a -> f b, all that's required is that you do provide those inputs. And indeed you almost have to make use of functionality specific to a and b. The implementer of the polymorphic signature doesn't get that freedom, they are restricted by the polymorphism to only doing things that would work for any possible choice.
As an aside, similarly to how rank 2 types add "another level" of this duality with the roles reversed (and rank N types allow arbitrarily many levels), a similar duality is also seen (flipped around again) in the constraints themselves. Consider again the signature:
for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b)
The caller of for is restricted by the Traversable and Applicative constraints when choosing the types t and f. The implementer gets the freedom to use any functions implied by those constraints, without worrying about how to prove the constraints are satisfied.
The first short answer is that Parser has an Applicative instance. The snippet
do
a' <- parseJSON a
b' <- parseJSON b
return (a', b')
has the type Parser (Whitelisted, WhitelistComment) which unifies with f b in the type signature
for :: (Traversable t, Applicative f) => t a -> (a -> f b) -> f (t b)
Since there's an Applicative Parser instance, it also satisfies that constraint. (I think I got the types for a' and b' right)
The second short answer is that a Monad is strictly more powerful than an Applicative, anywhere you need an Applicative you can use a Monad instead. Ever since the Monad-Applicative proposal was implemented, every Monad is also Applicative. The Monad class now looks like
class Applicative m => Monad m where
...
A Monad is strictly more powerful than an Applicative, anywhere you need an Applicative you can use a Monad instead with the following substitutions:
ap instead of <*>
return instead of pure
liftM instead of fmap
If you're writing some new type, SomeMonad, and have provided an instance for the Monad class you can use it to provide the instances for Applicative and Functor too.
import Control.Monad
instance Applicative SomeMonad where
pure = return
(<*>) = ap
instance Functor SomeMonad where
fmap = liftM
Related
While explaining to someone what a type class X is I struggle to find good examples of data structures which are exactly X.
So, I request examples for:
A type constructor which is not a Functor.
A type constructor which is a Functor, but not Applicative.
A type constructor which is an Applicative, but is not a Monad.
A type constructor which is a Monad.
I think there are plenty examples of Monad everywhere, but a good example of Monad with some relation to previous examples could complete the picture.
I look for examples which would be similar to each other, differing only in aspects important for belonging to the particular type class.
If one could manage to sneak up an example of Arrow somewhere in this hierarchy (is it between Applicative and Monad?), that would be great too!
A type constructor which is not a Functor:
newtype T a = T (a -> Int)
You can make a contravariant functor out of it, but not a (covariant) functor. Try writing fmap and you'll fail. Note that the contravariant functor version is reversed:
fmap :: Functor f => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a
A type constructor which is a functor, but not Applicative:
I don't have a good example. There is Const, but ideally I'd like a concrete non-Monoid and I can't think of any. All types are basically numeric, enumerations, products, sums, or functions when you get down to it. You can see below pigworker and I disagreeing about whether Data.Void is a Monoid;
instance Monoid Data.Void where
mempty = undefined
mappend _ _ = undefined
mconcat _ = undefined
Since _|_ is a legal value in Haskell, and in fact the only legal value of Data.Void, this meets the Monoid rules. I am unsure what unsafeCoerce has to do with it, because your program is no longer guaranteed not to violate Haskell semantics as soon as you use any unsafe function.
See the Haskell Wiki for an article on bottom (link) or unsafe functions (link).
I wonder if it is possible to create such a type constructor using a richer type system, such as Agda or Haskell with various extensions.
A type constructor which is an Applicative, but not a Monad:
newtype T a = T {multidimensional array of a}
You can make an Applicative out of it, with something like:
mkarray [(+10), (+100), id] <*> mkarray [1, 2]
== mkarray [[11, 101, 1], [12, 102, 2]]
But if you make it a monad, you could get a dimension mismatch. I suspect that examples like this are rare in practice.
A type constructor which is a Monad:
[]
About Arrows:
Asking where an Arrow lies on this hierarchy is like asking what kind of shape "red" is. Note the kind mismatch:
Functor :: * -> *
Applicative :: * -> *
Monad :: * -> *
but,
Arrow :: * -> * -> *
My style may be cramped by my phone, but here goes.
newtype Not x = Kill {kill :: x -> Void}
cannot be a Functor. If it were, we'd have
kill (fmap (const ()) (Kill id)) () :: Void
and the Moon would be made of green cheese.
Meanwhile
newtype Dead x = Oops {oops :: Void}
is a functor
instance Functor Dead where
fmap f (Oops corpse) = Oops corpse
but cannot be applicative, or we'd have
oops (pure ()) :: Void
and Green would be made of Moon cheese (which can actually happen, but only later in the evening).
(Extra note: Void, as in Data.Void is an empty datatype. If you try to use undefined to prove it's a Monoid, I'll use unsafeCoerce to prove that it isn't.)
Joyously,
newtype Boo x = Boo {boo :: Bool}
is applicative in many ways, e.g., as Dijkstra would have it,
instance Applicative Boo where
pure _ = Boo True
Boo b1 <*> Boo b2 = Boo (b1 == b2)
but it cannot be a Monad. To see why not, observe that return must be constantly Boo True or Boo False, and hence that
join . return == id
cannot possibly hold.
Oh yeah, I nearly forgot
newtype Thud x = The {only :: ()}
is a Monad. Roll your own.
Plane to catch...
I believe the other answers missed some simple and common examples:
A type constructor which is a Functor but not an Applicative. A simple example is a pair:
instance Functor ((,) r) where
fmap f (x,y) = (x, f y)
But there is no way how to define its Applicative instance without imposing additional restrictions on r. In particular, there is no way how to define pure :: a -> (r, a) for an arbitrary r.
A type constructor which is an Applicative, but is not a Monad. A well-known example is ZipList. (It's a newtype that wraps lists and provides different Applicative instance for them.)
fmap is defined in the usual way. But pure and <*> are defined as
pure x = ZipList (repeat x)
ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)
so pure creates an infinite list by repeating the given value, and <*> zips a list of functions with a list of values - applies i-th function to i-th element. (The standard <*> on [] produces all possible combinations of applying i-th function to j-th element.) But there is no sensible way how to define a monad (see this post).
How arrows fit into the functor/applicative/monad hierarchy?
See Idioms are oblivious, arrows are meticulous, monads are promiscuous by Sam Lindley, Philip Wadler, Jeremy Yallop. MSFP 2008. (They call applicative functors idioms.) The abstract:
We revisit the connection between three notions of computation: Moggi's monads, Hughes's arrows and McBride and Paterson's idioms (also called applicative functors). We show that idioms are equivalent to arrows that satisfy the type isomorphism A ~> B = 1 ~> (A -> B) and that monads are equivalent to arrows that satisfy the type isomorphism A ~> B = A -> (1 ~> B). Further, idioms embed into arrows and arrows embed into monads.
A good example for a type constructor which is not a functor is Set: You can't implement fmap :: (a -> b) -> f a -> f b, because without an additional constraint Ord b you can't construct f b.
I'd like to propose a more systematic approach to answering this question, and also to show examples that do not use any special tricks like the "bottom" values or infinite data types or anything like that.
When do type constructors fail to have type class instances?
In general, there are two reasons why a type constructor could fail to have an instance of a certain type class:
Cannot implement the type signatures of the required methods from the type class.
Can implement the type signatures but cannot satisfy the required laws.
Examples of the first kind are easier than those of the second kind because for the first kind, we just need to check whether one can implement a function with a given type signature, while for the second kind, we are required to prove that no implementation could possibly satisfy the laws.
Specific examples
A type constructor that cannot have a functor instance because the type cannot be implemented:
data F z a = F (a -> z)
This is a contrafunctor, not a functor, with respect to the type parameter a, because a in a contravariant position. It is impossible to implement a function with type signature (a -> b) -> F z a -> F z b.
A type constructor that is not a lawful functor even though the type signature of fmap can be implemented:
data Q a = Q(a -> Int, a)
fmap :: (a -> b) -> Q a -> Q b
fmap f (Q(g, x)) = Q(\_ -> g x, f x) -- this fails the functor laws!
The curious aspect of this example is that we can implement fmap of the correct type even though F cannot possibly be a functor because it uses a in a contravariant position. So this implementation of fmap shown above is misleading - even though it has the correct type signature (I believe this is the only possible implementation of that type signature), the functor laws are not satisfied. For example, fmap id ≠ id, because let (Q(f,_)) = fmap id (Q(read,"123")) in f "456" is 123, but let (Q(f,_)) = id (Q(read,"123")) in f "456" is 456.
In fact, F is only a profunctor, - it is neither a functor nor a contrafunctor.
A lawful functor that is not applicative because the type signature of pure cannot be implemented: take the Writer monad (a, w) and remove the constraint that w should be a monoid. It is then impossible to construct a value of type (a, w) out of a.
A functor that is not applicative because the type signature of <*> cannot be implemented: data F a = Either (Int -> a) (String -> a).
A functor that is not lawful applicative even though the type class methods can be implemented:
data P a = P ((a -> Int) -> Maybe a)
The type constructor P is a functor because it uses a only in covariant positions.
instance Functor P where
fmap :: (a -> b) -> P a -> P b
fmap fab (P pa) = P (\q -> fmap fab $ pa (q . fab))
The only possible implementation of the type signature of <*> is a function that always returns Nothing:
(<*>) :: P (a -> b) -> P a -> P b
(P pfab) <*> (P pa) = \_ -> Nothing -- fails the laws!
But this implementation does not satisfy the identity law for applicative functors.
A functor that is Applicative but not a Monad because the type signature of bind cannot be implemented.
I do not know any such examples!
A functor that is Applicative but not a Monad because laws cannot be satisfied even though the type signature of bind can be implemented.
This example has generated quite a bit of discussion, so it is safe to say that proving this example correct is not easy. But several people have verified this independently by different methods. See Is `data PoE a = Empty | Pair a a` a monad? for additional discussion.
data B a = Maybe (a, a)
deriving Functor
instance Applicative B where
pure x = Just (x, x)
b1 <*> b2 = case (b1, b2) of
(Just (x1, y1), Just (x2, y2)) -> Just((x1, x2), (y1, y2))
_ -> Nothing
It is somewhat cumbersome to prove that there is no lawful Monad instance. The reason for the non-monadic behavior is that there is no natural way of implementing bind when a function f :: a -> B b could return Nothing or Just for different values of a.
It is perhaps clearer to consider Maybe (a, a, a), which is also not a monad, and to try implementing join for that. One will find that there is no intuitively reasonable way of implementing join.
join :: Maybe (Maybe (a, a, a), Maybe (a, a, a), Maybe (a, a, a)) -> Maybe (a, a, a)
join Nothing = Nothing
join Just (Nothing, Just (x1,x2,x3), Just (y1,y2,y3)) = ???
join Just (Just (x1,x2,x3), Nothing, Just (y1,y2,y3)) = ???
-- etc.
In the cases indicated by ???, it seems clear that we cannot produce Just (z1, z2, z3) in any reasonable and symmetric manner out of six different values of type a. We could certainly choose some arbitrary subset of these six values, -- for instance, always take the first nonempty Maybe - but this would not satisfy the laws of the monad. Returning Nothing will also not satisfy the laws.
A tree-like data structure that is not a monad even though it has associativity for bind - but fails the identity laws.
The usual tree-like monad (or "a tree with functor-shaped branches") is defined as
data Tr f a = Leaf a | Branch (f (Tr f a))
This is a free monad over the functor f. The shape of the data is a tree where each branch point is a "functor-ful" of subtrees. The standard binary tree would be obtained with type f a = (a, a).
If we modify this data structure by making also the leaves in the shape of the functor f, we obtain what I call a "semimonad" - it has bind that satisfies the naturality and the associativity laws, but its pure method fails one of the identity laws. "Semimonads are semigroups in the category of endofunctors, what's the problem?" This is the type class Bind.
For simplicity, I define the join method instead of bind:
data Trs f a = Leaf (f a) | Branch (f (Trs f a))
join :: Trs f (Trs f a) -> Trs f a
join (Leaf ftrs) = Branch ftrs
join (Branch ftrstrs) = Branch (fmap #f join ftrstrs)
The branch grafting is standard, but the leaf grafting is non-standard and produces a Branch. This is not a problem for the associativity law but breaks one of the identity laws.
When do polynomial types have monad instances?
Neither of the functors Maybe (a, a) and Maybe (a, a, a) can be given a lawful Monad instance, although they are obviously Applicative.
These functors have no tricks - no Void or bottom anywhere, no tricky laziness/strictness, no infinite structures, and no type class constraints. The Applicative instance is completely standard. The functions return and bind can be implemented for these functors but will not satisfy the laws of the monad. In other words, these functors are not monads because a specific structure is missing (but it is not easy to understand what exactly is missing). As an example, a small change in the functor can make it into a monad: data Maybe a = Nothing | Just a is a monad. Another similar functor data P12 a = Either a (a, a) is also a monad.
Constructions for polynomial monads
In general, here are some constructions that produce lawful Monads out of polynomial types. In all these constructions, M is a monad:
type M a = Either c (w, a) where w is any monoid
type M a = m (Either c (w, a)) where m is any monad and w is any monoid
type M a = (m1 a, m2 a) where m1 and m2 are any monads
type M a = Either a (m a) where m is any monad
The first construction is WriterT w (Either c), the second construction is WriterT w (EitherT c m). The third construction is a component-wise product of monads: pure #M is defined as the component-wise product of pure #m1 and pure #m2, and join #M is defined by omitting cross-product data (e.g. m1 (m1 a, m2 a) is mapped to m1 (m1 a) by omitting the second part of the tuple):
join :: (m1 (m1 a, m2 a), m2 (m1 a, m2 a)) -> (m1 a, m2 a)
join (m1x, m2x) = (join #m1 (fmap fst m1x), join #m2 (fmap snd m2x))
The fourth construction is defined as
data M m a = Either a (m a)
instance Monad m => Monad M m where
pure x = Left x
join :: Either (M m a) (m (M m a)) -> M m a
join (Left mma) = mma
join (Right me) = Right $ join #m $ fmap #m squash me where
squash :: M m a -> m a
squash (Left x) = pure #m x
squash (Right ma) = ma
I have checked that all four constructions produce lawful monads.
I conjecture that there are no other constructions for polynomial monads. For example, the functor Maybe (Either (a, a) (a, a, a, a)) is not obtained through any of these constructions and so is not monadic. However, Either (a, a) (a, a, a) is monadic because it is isomorphic to the product of three monads a, a, and Maybe a. Also, Either (a,a) (a,a,a,a) is monadic because it is isomorphic to the product of a and Either a (a, a, a).
The four constructions shown above will allow us to obtain any sum of any number of products of any number of a's, for example Either (Either (a, a) (a, a, a, a)) (a, a, a, a, a)) and so on. All such type constructors will have (at least one) Monad instance.
It remains to be seen, of course, what use cases might exist for such monads. Another issue is that the Monad instances derived via constructions 1-4 are in general not unique. For example, the type constructor type F a = Either a (a, a) can be given a Monad instance in two ways: by construction 4 using the monad (a, a), and by construction 3 using the type isomorphism Either a (a, a) = (a, Maybe a). Again, finding use cases for these implementations is not immediately obvious.
A question remains - given an arbitrary polynomial data type, how to recognize whether it has a Monad instance. I do not know how to prove that there are no other constructions for polynomial monads. I don't think any theory exists so far to answer this question.
In Scalaz every Monad instance is automatically an instance of Applicative.
implicit val listInstance = new Monad[List] {
def point[A](a: => A) = List(a)
def bind[A, B](fa: List[A])(f: A => List[B]) = fa flatMap f
}
List(2) <*> List((x: Int) => x + 1) // Works!
Another example: Arrow is automatically a Profunctor.
However, in Haskell I must provide an instance of Applicative for every Monad again and again.
Is it possible to avoid this repetitive job?
The problem comes when there are two places from which to derive the Applicative instance. For instance, suppose m is the type a b where Arrow a. Then there's an obvious instance of Applicative from this definition as well. Which one should the compiler use? It should work out the same, of course, but Haskell has no way to check this. By making us write out the instances, Haskell at least forces us to think about the consistency of our definitions.
If you want, there's the WrappedMonad class in Control.Applicative, which provides all the obvious instances with a newtype wrapper, but using WrapMonad and unwrapMonad all the time isn't that attractive either.
It isn't currently possible, though it would be if you changed the existing library to support this. Turning DefaultSignatures on would let you write
class Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
default pure :: Monad f => a -> f a
default (<*>) :: Monad f => f (a -> b) -> f a -> f b
pure = return
(<*>) = ap
Then once you had implemented instance Monad M where {- ... -}, a simple instance Applicative M (with no where or method definitions) would inherit these default implementations. I'm not sure why this wasn't done.
I have a data structure (it's a specific subclass of rose-tree that forms a lattice with greatest-lower bound and lowest-upper bound functions), and it supports two perfectly reasonable functions to serve as the Monoid class's mappend.
Is there any way to support anonymous Monoid instances in haskell? Is this an instance where I should consider using something like Template-Haskell to generate my typeclasses for me?
What I'd love is a makeMonoid :: (RT a -> RT a -> RT a) -> Monoid a to let me create the instance on the fly, but I understand that that's incoherent with the stock typesystem as I understand it.
I'm okay with it if I just need to pick a default merge function and write newtypes for other merges, just curious
You can create "local" instances of Monoid on the fly, using the tools in the reflection package. There's a ready-made example in the repository. This answer explains it a little.
This is a newtype wrapper over values of type a, on which we will define our Monoid instance.
newtype M a s = M { runM :: a } deriving (Eq,Ord)
Notice that there is a phantom type s that does not appear in the right hand side. It will carry extra information necessary for the local Monoid instance to work.
This is a record whose fields represent the two operation of the Monoid class:
data Monoid_ a = Monoid_ { mappend_ :: a -> a -> a, mempty_ :: a }
The following is the Monoid instance definition for M:
instance Reifies s (Monoid_ a) => Monoid (M a s) where
mappend a b = M $ mappend_ (reflect a) (runM a) (runM b)
mempty = a where a = M $ mempty_ (reflect a)
It says: "whenever s is a type-level representation of our Monoid dictionary Monoid_, we can reflect it back to obtain the dictionary, and use the fields to implement the Monoid operations for M".
Notice that the actual value a passed to reflect is not used, it is passed only as a "proxy" of type M a s that tells reflect which type (s) to use to "bring back the record".
The actual local instance is constructed using the reify function:
withMonoid :: (a -> a -> a) -> a -> (forall s. Reifies s (Monoid_ a) => M a s) -> a
withMonoid f z v = reify (Monoid_ f z) (runM . asProxyOf v)
asProxyOf :: f s -> Proxy s -> f s
asProxyOf a _ = a
The asProxyOf function is a trick to convince the compiler that the phantom type used in the monoid is the same as the one in the Proxy supplied by reify.
While explaining to someone what a type class X is I struggle to find good examples of data structures which are exactly X.
So, I request examples for:
A type constructor which is not a Functor.
A type constructor which is a Functor, but not Applicative.
A type constructor which is an Applicative, but is not a Monad.
A type constructor which is a Monad.
I think there are plenty examples of Monad everywhere, but a good example of Monad with some relation to previous examples could complete the picture.
I look for examples which would be similar to each other, differing only in aspects important for belonging to the particular type class.
If one could manage to sneak up an example of Arrow somewhere in this hierarchy (is it between Applicative and Monad?), that would be great too!
A type constructor which is not a Functor:
newtype T a = T (a -> Int)
You can make a contravariant functor out of it, but not a (covariant) functor. Try writing fmap and you'll fail. Note that the contravariant functor version is reversed:
fmap :: Functor f => (a -> b) -> f a -> f b
contramap :: Contravariant f => (a -> b) -> f b -> f a
A type constructor which is a functor, but not Applicative:
I don't have a good example. There is Const, but ideally I'd like a concrete non-Monoid and I can't think of any. All types are basically numeric, enumerations, products, sums, or functions when you get down to it. You can see below pigworker and I disagreeing about whether Data.Void is a Monoid;
instance Monoid Data.Void where
mempty = undefined
mappend _ _ = undefined
mconcat _ = undefined
Since _|_ is a legal value in Haskell, and in fact the only legal value of Data.Void, this meets the Monoid rules. I am unsure what unsafeCoerce has to do with it, because your program is no longer guaranteed not to violate Haskell semantics as soon as you use any unsafe function.
See the Haskell Wiki for an article on bottom (link) or unsafe functions (link).
I wonder if it is possible to create such a type constructor using a richer type system, such as Agda or Haskell with various extensions.
A type constructor which is an Applicative, but not a Monad:
newtype T a = T {multidimensional array of a}
You can make an Applicative out of it, with something like:
mkarray [(+10), (+100), id] <*> mkarray [1, 2]
== mkarray [[11, 101, 1], [12, 102, 2]]
But if you make it a monad, you could get a dimension mismatch. I suspect that examples like this are rare in practice.
A type constructor which is a Monad:
[]
About Arrows:
Asking where an Arrow lies on this hierarchy is like asking what kind of shape "red" is. Note the kind mismatch:
Functor :: * -> *
Applicative :: * -> *
Monad :: * -> *
but,
Arrow :: * -> * -> *
My style may be cramped by my phone, but here goes.
newtype Not x = Kill {kill :: x -> Void}
cannot be a Functor. If it were, we'd have
kill (fmap (const ()) (Kill id)) () :: Void
and the Moon would be made of green cheese.
Meanwhile
newtype Dead x = Oops {oops :: Void}
is a functor
instance Functor Dead where
fmap f (Oops corpse) = Oops corpse
but cannot be applicative, or we'd have
oops (pure ()) :: Void
and Green would be made of Moon cheese (which can actually happen, but only later in the evening).
(Extra note: Void, as in Data.Void is an empty datatype. If you try to use undefined to prove it's a Monoid, I'll use unsafeCoerce to prove that it isn't.)
Joyously,
newtype Boo x = Boo {boo :: Bool}
is applicative in many ways, e.g., as Dijkstra would have it,
instance Applicative Boo where
pure _ = Boo True
Boo b1 <*> Boo b2 = Boo (b1 == b2)
but it cannot be a Monad. To see why not, observe that return must be constantly Boo True or Boo False, and hence that
join . return == id
cannot possibly hold.
Oh yeah, I nearly forgot
newtype Thud x = The {only :: ()}
is a Monad. Roll your own.
Plane to catch...
I believe the other answers missed some simple and common examples:
A type constructor which is a Functor but not an Applicative. A simple example is a pair:
instance Functor ((,) r) where
fmap f (x,y) = (x, f y)
But there is no way how to define its Applicative instance without imposing additional restrictions on r. In particular, there is no way how to define pure :: a -> (r, a) for an arbitrary r.
A type constructor which is an Applicative, but is not a Monad. A well-known example is ZipList. (It's a newtype that wraps lists and provides different Applicative instance for them.)
fmap is defined in the usual way. But pure and <*> are defined as
pure x = ZipList (repeat x)
ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs)
so pure creates an infinite list by repeating the given value, and <*> zips a list of functions with a list of values - applies i-th function to i-th element. (The standard <*> on [] produces all possible combinations of applying i-th function to j-th element.) But there is no sensible way how to define a monad (see this post).
How arrows fit into the functor/applicative/monad hierarchy?
See Idioms are oblivious, arrows are meticulous, monads are promiscuous by Sam Lindley, Philip Wadler, Jeremy Yallop. MSFP 2008. (They call applicative functors idioms.) The abstract:
We revisit the connection between three notions of computation: Moggi's monads, Hughes's arrows and McBride and Paterson's idioms (also called applicative functors). We show that idioms are equivalent to arrows that satisfy the type isomorphism A ~> B = 1 ~> (A -> B) and that monads are equivalent to arrows that satisfy the type isomorphism A ~> B = A -> (1 ~> B). Further, idioms embed into arrows and arrows embed into monads.
A good example for a type constructor which is not a functor is Set: You can't implement fmap :: (a -> b) -> f a -> f b, because without an additional constraint Ord b you can't construct f b.
I'd like to propose a more systematic approach to answering this question, and also to show examples that do not use any special tricks like the "bottom" values or infinite data types or anything like that.
When do type constructors fail to have type class instances?
In general, there are two reasons why a type constructor could fail to have an instance of a certain type class:
Cannot implement the type signatures of the required methods from the type class.
Can implement the type signatures but cannot satisfy the required laws.
Examples of the first kind are easier than those of the second kind because for the first kind, we just need to check whether one can implement a function with a given type signature, while for the second kind, we are required to prove that no implementation could possibly satisfy the laws.
Specific examples
A type constructor that cannot have a functor instance because the type cannot be implemented:
data F z a = F (a -> z)
This is a contrafunctor, not a functor, with respect to the type parameter a, because a in a contravariant position. It is impossible to implement a function with type signature (a -> b) -> F z a -> F z b.
A type constructor that is not a lawful functor even though the type signature of fmap can be implemented:
data Q a = Q(a -> Int, a)
fmap :: (a -> b) -> Q a -> Q b
fmap f (Q(g, x)) = Q(\_ -> g x, f x) -- this fails the functor laws!
The curious aspect of this example is that we can implement fmap of the correct type even though F cannot possibly be a functor because it uses a in a contravariant position. So this implementation of fmap shown above is misleading - even though it has the correct type signature (I believe this is the only possible implementation of that type signature), the functor laws are not satisfied. For example, fmap id ≠ id, because let (Q(f,_)) = fmap id (Q(read,"123")) in f "456" is 123, but let (Q(f,_)) = id (Q(read,"123")) in f "456" is 456.
In fact, F is only a profunctor, - it is neither a functor nor a contrafunctor.
A lawful functor that is not applicative because the type signature of pure cannot be implemented: take the Writer monad (a, w) and remove the constraint that w should be a monoid. It is then impossible to construct a value of type (a, w) out of a.
A functor that is not applicative because the type signature of <*> cannot be implemented: data F a = Either (Int -> a) (String -> a).
A functor that is not lawful applicative even though the type class methods can be implemented:
data P a = P ((a -> Int) -> Maybe a)
The type constructor P is a functor because it uses a only in covariant positions.
instance Functor P where
fmap :: (a -> b) -> P a -> P b
fmap fab (P pa) = P (\q -> fmap fab $ pa (q . fab))
The only possible implementation of the type signature of <*> is a function that always returns Nothing:
(<*>) :: P (a -> b) -> P a -> P b
(P pfab) <*> (P pa) = \_ -> Nothing -- fails the laws!
But this implementation does not satisfy the identity law for applicative functors.
A functor that is Applicative but not a Monad because the type signature of bind cannot be implemented.
I do not know any such examples!
A functor that is Applicative but not a Monad because laws cannot be satisfied even though the type signature of bind can be implemented.
This example has generated quite a bit of discussion, so it is safe to say that proving this example correct is not easy. But several people have verified this independently by different methods. See Is `data PoE a = Empty | Pair a a` a monad? for additional discussion.
data B a = Maybe (a, a)
deriving Functor
instance Applicative B where
pure x = Just (x, x)
b1 <*> b2 = case (b1, b2) of
(Just (x1, y1), Just (x2, y2)) -> Just((x1, x2), (y1, y2))
_ -> Nothing
It is somewhat cumbersome to prove that there is no lawful Monad instance. The reason for the non-monadic behavior is that there is no natural way of implementing bind when a function f :: a -> B b could return Nothing or Just for different values of a.
It is perhaps clearer to consider Maybe (a, a, a), which is also not a monad, and to try implementing join for that. One will find that there is no intuitively reasonable way of implementing join.
join :: Maybe (Maybe (a, a, a), Maybe (a, a, a), Maybe (a, a, a)) -> Maybe (a, a, a)
join Nothing = Nothing
join Just (Nothing, Just (x1,x2,x3), Just (y1,y2,y3)) = ???
join Just (Just (x1,x2,x3), Nothing, Just (y1,y2,y3)) = ???
-- etc.
In the cases indicated by ???, it seems clear that we cannot produce Just (z1, z2, z3) in any reasonable and symmetric manner out of six different values of type a. We could certainly choose some arbitrary subset of these six values, -- for instance, always take the first nonempty Maybe - but this would not satisfy the laws of the monad. Returning Nothing will also not satisfy the laws.
A tree-like data structure that is not a monad even though it has associativity for bind - but fails the identity laws.
The usual tree-like monad (or "a tree with functor-shaped branches") is defined as
data Tr f a = Leaf a | Branch (f (Tr f a))
This is a free monad over the functor f. The shape of the data is a tree where each branch point is a "functor-ful" of subtrees. The standard binary tree would be obtained with type f a = (a, a).
If we modify this data structure by making also the leaves in the shape of the functor f, we obtain what I call a "semimonad" - it has bind that satisfies the naturality and the associativity laws, but its pure method fails one of the identity laws. "Semimonads are semigroups in the category of endofunctors, what's the problem?" This is the type class Bind.
For simplicity, I define the join method instead of bind:
data Trs f a = Leaf (f a) | Branch (f (Trs f a))
join :: Trs f (Trs f a) -> Trs f a
join (Leaf ftrs) = Branch ftrs
join (Branch ftrstrs) = Branch (fmap #f join ftrstrs)
The branch grafting is standard, but the leaf grafting is non-standard and produces a Branch. This is not a problem for the associativity law but breaks one of the identity laws.
When do polynomial types have monad instances?
Neither of the functors Maybe (a, a) and Maybe (a, a, a) can be given a lawful Monad instance, although they are obviously Applicative.
These functors have no tricks - no Void or bottom anywhere, no tricky laziness/strictness, no infinite structures, and no type class constraints. The Applicative instance is completely standard. The functions return and bind can be implemented for these functors but will not satisfy the laws of the monad. In other words, these functors are not monads because a specific structure is missing (but it is not easy to understand what exactly is missing). As an example, a small change in the functor can make it into a monad: data Maybe a = Nothing | Just a is a monad. Another similar functor data P12 a = Either a (a, a) is also a monad.
Constructions for polynomial monads
In general, here are some constructions that produce lawful Monads out of polynomial types. In all these constructions, M is a monad:
type M a = Either c (w, a) where w is any monoid
type M a = m (Either c (w, a)) where m is any monad and w is any monoid
type M a = (m1 a, m2 a) where m1 and m2 are any monads
type M a = Either a (m a) where m is any monad
The first construction is WriterT w (Either c), the second construction is WriterT w (EitherT c m). The third construction is a component-wise product of monads: pure #M is defined as the component-wise product of pure #m1 and pure #m2, and join #M is defined by omitting cross-product data (e.g. m1 (m1 a, m2 a) is mapped to m1 (m1 a) by omitting the second part of the tuple):
join :: (m1 (m1 a, m2 a), m2 (m1 a, m2 a)) -> (m1 a, m2 a)
join (m1x, m2x) = (join #m1 (fmap fst m1x), join #m2 (fmap snd m2x))
The fourth construction is defined as
data M m a = Either a (m a)
instance Monad m => Monad M m where
pure x = Left x
join :: Either (M m a) (m (M m a)) -> M m a
join (Left mma) = mma
join (Right me) = Right $ join #m $ fmap #m squash me where
squash :: M m a -> m a
squash (Left x) = pure #m x
squash (Right ma) = ma
I have checked that all four constructions produce lawful monads.
I conjecture that there are no other constructions for polynomial monads. For example, the functor Maybe (Either (a, a) (a, a, a, a)) is not obtained through any of these constructions and so is not monadic. However, Either (a, a) (a, a, a) is monadic because it is isomorphic to the product of three monads a, a, and Maybe a. Also, Either (a,a) (a,a,a,a) is monadic because it is isomorphic to the product of a and Either a (a, a, a).
The four constructions shown above will allow us to obtain any sum of any number of products of any number of a's, for example Either (Either (a, a) (a, a, a, a)) (a, a, a, a, a)) and so on. All such type constructors will have (at least one) Monad instance.
It remains to be seen, of course, what use cases might exist for such monads. Another issue is that the Monad instances derived via constructions 1-4 are in general not unique. For example, the type constructor type F a = Either a (a, a) can be given a Monad instance in two ways: by construction 4 using the monad (a, a), and by construction 3 using the type isomorphism Either a (a, a) = (a, Maybe a). Again, finding use cases for these implementations is not immediately obvious.
A question remains - given an arbitrary polynomial data type, how to recognize whether it has a Monad instance. I do not know how to prove that there are no other constructions for polynomial monads. I don't think any theory exists so far to answer this question.
I would like to write something like:
{-# LANGUAGE FlexibleContexts,FlexibleInstances #-}
import Data.ByteString.Char8 (ByteString,pack)
import Data.Foldable (Foldable)
class (Show a) => Rows a where
rRepr :: a -> [ByteString]
rRepr = (:[]) . pack . show
instance (Foldable f,Show (f a)) => Rows (f a) where
rRepr = const []
meaning that f a instantiate Rows if f instantiate Foldable and f a instantiate Show. When I run ghc I get:
Constraint is no smaller than the instance head
in the constraint: Show (f a)
(Use -XUndecidableInstances to permit this)
In the instance declaration for `Rows (f a)'
I have two questions:
what "smaller" means in the error and what is the problem?
what is the right way to define what I want without using UndecidableInstances?
Let's play compiler: we have a type (f a) we'd like to see if it is a valid satisfier of a Rows constraint. To do so, we need to dispatch a proof that (f a) satisfies Show (f a) as well. This isn't a problem unless someone writes an
instance Rows (f a) => Show (f a) where ...
in which case I'm back where I began. Encoding an infinite loop like this is sort of foolish, but Haskell statically ensures that it's actually impossible unless you ask for UndecidableInstances.
Normally Haskell ensures that each step of a "resolution chase" reduces the size of the type by at least 1 constructor. This leads to a really simple proof by structural induction that we'll end up with a bare type in a finite number of resolutions.
This is overly restrictive, clearly some instance resolution steps are meaningful, useful, and total even if they don't immediately reduce the constructor tree. This same kind of totality restriction applies in languages like Agda and Coq and often it's a bit of an illustrative challenge to manipulate your algorithm into one which proceeds by structural induction.
So how can we fix it? One way is to lose the Show constraint on the class definition use an instance like Show1 from prelude-extras.
class Show1 f where ...
show1 :: (Show1 f, Show a) => f a -> String -- not an instance definition!
and then have instance (Foldable f, Show1 f, Show a) => Rows (f a) where ... which works in my testing. You can then write a default instance as a standalone function.
defRRepr :: Show a => a -> [ByteString]
defRRepr = (:[]) . pack . show
and use it whenever writing an instance definition for a Showable thing.
The other solution is to use newtype wrappers to allow Haskell to see that a "layer" of resolution has been removed.
instance (Foldable f, Show (f a)) => Rows (FoldableRow f a) where
rRepr = const [] . unFR
newtype FoldableRow f a = FR { unFR :: f a } deriving (Show)