61

I am trying to define a new monad and I am getting a strange error

newmonad.hs

newtype Wrapped a = Wrap {unwrap :: a}
instance Monad Wrapped where
  (>>=) (Wrap x) f =  f x
  return x = Wrap x

main = do
  putStrLn "yay"
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 7.10.1

$ ghc newmonad.hs 
[1 of 1] Compiling Main             ( newmonad.hs, newmonad.o )

newmonad.hs:2:10:
    No instance for (Applicative Wrapped)
      arising from the superclasses of an instance declaration
    In the instance declaration for ‘Monad Wrapped’

Why do I need to define an instance of Applicative?

recursion.ninja
  • 5,377
  • 7
  • 46
  • 78
fakedrake
  • 6,528
  • 8
  • 41
  • 64
  • 3
    By the way, you might want to get used to use a capital letter for the first letter in your Haskell source files name. This is because file names should match module names which do start with a capital letter. It doesn't matter much for scripting such as in your case, of course. Best of luck! – MasterMastic Jul 28 '15 at 15:46

2 Answers2

94

This is the Applicative Monad Proposal (AMP). Now whenever you declare something as Monad, you also have to declare it as Applicative (and therefore Functor). Mathematically speaking, every monad is an applicative functor, so this makes sense.

You can do the following to remove the error:

instance Functor Wrap where
  fmap f (Wrap x) = Wrap (f x)

instance Applicative Wrap where
  pure = Wrap
  Wrap f <*> Wrap x = Wrap (f x)

https://wiki.haskell.org/Functor-Applicative-Monad_Proposal

Edit: Maybe I should point out more clearly that this is a recent thing? The code you posted used to work before, but with recent versions of GHC you'll get an error. It's a breaking change.

Edit: The following declarations should work for any monad:

import Control.Applicative -- Otherwise you can't do the Applicative instance.
import Control.Monad (liftM, ap)

instance Functor ??? where
  fmap = liftM

instance Applicative ??? where
  pure  = return
  (<*>) = ap

Depending on the monad in question, there may be more efficient implementations possible, but this is a simple starting point.

MathematicalOrchid
  • 61,854
  • 19
  • 123
  • 220
  • Being new to haskell it seems that Applicatives are generally the most generic way to do things and Monads are a bit redundant? – fakedrake Jul 27 '15 at 13:02
  • 6
    Monads let you do things that are impossible with plain Applicative alone. In particular, choosing which action to run next based on the result of the previous action. – MathematicalOrchid Jul 27 '15 at 13:05
  • 7
    Specifically, the recent version of GHC at which this becomes an error is version 7.10. – Daniel Martin Jul 27 '15 at 13:50
  • 7
    Functors are more generic than Applicatives, and Applicatives are more generic than Monads. Powerfulness (i.e. the number of different operations you can perform on them) works the other way round. – Cubic Jul 27 '15 at 13:50
  • 1
    @fakedrake A nice question about this topic: [Difference between Monad and Applicative in Haskell](http://stackoverflow.com/questions/23342184/difference-between-monad-and-applicative-in-haskell). – duplode Jul 27 '15 at 14:37
  • 7
    This probably will be a frequent question for a while for people using new GHC with old tutorials etc. To make this answer more useful for others coming upon it, maybe you could give an `Applicative`/`Functor` definition that works generically for *all* `Monad`s? (E.g. using `do` notation, or `liftM` and `ap` (although those require an import.)) – Ørjan Johansen Jul 27 '15 at 15:03
  • @ØrjanJohansen Fair comment. Is this actually the first question, or is it a dup of something else already? – MathematicalOrchid Jul 27 '15 at 15:46
  • I looked a bit better and [found a dup](http://stackoverflow.com/questions/29844824/must-i-implement-applicative-and-functor-to-implement-a-monad) (although the accepted answer is a bit buggy, which makes me a little reluctant to close this one...). – Ørjan Johansen Jul 27 '15 at 16:09
  • @ØrjanJohansen we might [close the old question as a dup of this one](http://meta.stackexchange.com/questions/147643/should-i-vote-to-close-a-duplicate-question-even-though-its-much-newer-and-ha). – duplode Jul 27 '15 at 17:20
  • 3
    The migration guide at https://ghc.haskell.org/trac/ghc/wiki/Migration/7.10 says "DO NOT USE `pure = return`". (I have no idea what any of this means at this point, I am simply pointing out something that the guide is saying) – Motorhead Jan 15 '16 at 23:31
  • @S.N. Is it not because it is preferable to have general code in the top-most class? That way, if it turns out not to fit in a Monad, that instance can just be removed and it would still work. – Janus Troelsen Feb 25 '17 at 16:02
  • 2
    I find it strange that Haskell does not automatically derive `Functor` and `Applicative` instances from a `Monad` instance and requires the user to write that boilerplate. – Alexey Jun 24 '17 at 09:49
  • I believe it should be 'fmap' not 'famp' and 'Wrap' not 'wrap' – qbolec Sep 07 '17 at 19:17
  • 1
    I must say, one of the most enlightening chapters I've read on this topic is http://learnyouahaskell.com/functors-applicative-functors-and-monoids – and it also gave me a good perspective on the rationale behind this change. – Ashesh Jan 01 '18 at 17:57
2

The most normalized and unobtrusive answer is :-

as Monad is dependent upon Applicative

class Applicative m => Monad m where ...

and Applicative is dependent upon Functor

class Functor f => Applicative f where ...

we need the instance definitions

> instance Functor Wrapped where
>     fmap = liftM

and

> instance Applicative Wrapped where
>     pure = return
>     (<*>) = ap
AaronNGray
  • 123
  • 2
  • 12