I'm getting to grips with functors, applicatives and monads.
These examples are just to illustrate the basics:
data User a = Age a deriving (Show, Eq, Ord)
Functor (apply a non-context function to a single context datatype):
instance Functor User where
fmap f (Age a) = Age (f a)
functorFunction :: Int -> Int
functorFunction e = e + 1
main = do
print $ fmap functorFunction (Age 22)
Applicative (apply a simple function to multiple context datatypes):
instance Applicative User where
pure a = Age a
(<*>) (Age a) = fmap a
applicativeFunction :: Int -> Int -> Int
applicativeFunction e1 e2 = e1 + e2
main = do
print $ pure (applicativeFunction) <*> (Age 44) <*> (Age 65)
I've going through learnyouahaskell and haven't been able to find a simple explanation of
1) how to define a monad structure for my 'User a' type, and 2) what functionality a monad provides versus, say, an applicative functor?
(Preliminary note: Learn You a Haskell predates
Applicative
becoming a superclass ofMonad
. For that reason, and unlike the book suggests, with recent versions of GHC there is no need of implementingreturn
-- by default, it is the same aspure
. That being so, I will jump directly to(>>=)
.)One nice thing about methods with very general types such as
(>>=)
...... is that they are so general that there are few sensible ways of implementing them -- often just one. If we specialise
(>>=)
for your type, we get:So
(>>=)
is supposed to take anUser a
and ana -> User b
and use them to produce anUser b
. Given that the function takes ana
value, the first thing to try is looking for ana
value to pass to it. We do have such a value: the one wrapped by theAge
constructor in theUser a
value:To write a
Monad
instance in good conscience, we should check whether it follows the monad laws:That can be done with (your favourite equivalent of) pen and paper:
Here I will leave it to the question arrowd suggested. I will only note that your example doesn't give you enough to really appreciate the difference, as the
User
context is too simple to let you do anything interesting with(>>=)
(as Benjamin Hodgson points out, it is isomorphic toIdentity
, the dummy functor).Maybe
, which is used by the accepted answer of the linked question, is quite a bit more illustrative.