0

To my knowledge, Functors are those which have map() and Monads are those which also have flatMap(). All Monads are Functors but not vice-versa. What prevents Functors to implement a flatMap() and be a Monad? Are there any Functors which stayed that way due to some limitation. Can you please provide some examples. Thanks.

Gopal S Akshintala
  • 1,933
  • 1
  • 17
  • 24

2 Answers2

4

The statement all monads are functors means that, using only the methods from Monad, we can implement the methods from Functor. This can indeed be done, which is why we say that all monads are functors. I don’t know Vavr, but here’s some code in Haskell which does this:

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}

instance Monad m => Functor m where
    fmap f x = x >>= (\x' -> return (f x'))

By contrast, the statement all functors are monads means that, using only the methods from Functor, we can implement the methods from Monad. And this can’t be done, since you can do things with monads which you can’t do with functors. So we say that not all functors are monads.

Micha Wiedenmann
  • 19,979
  • 21
  • 92
  • 137
bradrn
  • 8,337
  • 2
  • 22
  • 51
  • Is this pseudo Haskell? I cannot declare a Functor instance: "Illegal instance delaration for `Functor m`". https://repl.it/repls/TiredThunderousMigration – Micha Wiedenmann Oct 02 '19 at 10:52
  • @MichaWiedenmann `{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} ` is required for this kind of instance declaration. Those are pretty common language extensions, you'll actually find them on (my estimate) half of all Haskell source files. (But even with those extensions, it will of course give errors if you write that instance, because it conflicts with directly-declared `Functor` instances.) – leftaroundabout Oct 02 '19 at 11:24
  • @leftaroundabout Thanks for editing that in! It looks like you’ve been correcting many of my other answers lately, so thank you for those ones as well! – bradrn Oct 02 '19 at 23:28
  • @MichaWiedenmann I did intend it to be somewhat ‘pseudo Haskell’. You can’t actually define such an instance because it conflicts with many other Functor instances for types with already-defined Monad instances, but it shows that such an instance _can_ be defined in a way that typechecks and (sort-of) works. A better example would have been to define a new function `monad_fmap :: Monad m => (a -> b) -> m a -> m b`, and implement that instead of `fmap`. – bradrn Oct 02 '19 at 23:30
  • @bradrn `monad_fmap` a.k.a. `liftM`. :) – Will Ness Oct 03 '19 at 08:41
  • @WillNess I know this already exists as `liftM`. I just wanted to make the name absolutely clear even for people who may not know about `liftM`. – bradrn Oct 03 '19 at 10:56
  • so it's good to be made aware of it, right? seeing something from several POVs often helps to see it clearer. – Will Ness Oct 03 '19 at 11:08
  • Good point @WillNess! I thought you were just correcting me, but you’re right in that different POVs are important. – bradrn Oct 03 '19 at 11:57
1

If a type implements flatMap() (as well as return()/unit()/emit()/inject()/wrap()/...), it is already a Monad, by definition.

A "Functor" is a very narrow view of a given type. It only considers its ability to map(). There's no regard to any specifics of the given type, when regarding it as an instance of "Functor".

If a given type can have a law-abiding(*) flatMap() implemented (as well as return()), then it can also be viewed as a lawful instance of "Monad".

If an opaque type does not supply us with return(), it can't be viewed as a Monad, is one possibility.

Another is flatMap() which does not follow the Monad laws.

edit: (*) thanks to @leftaroundabout for pointing out about the laws. on the other hand declaring an unlawful Monad instance in Haskell is still technically possible, even though it's certainly not advisable.

Will Ness
  • 70,110
  • 9
  • 98
  • 181