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
Applicativebecoming 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 aand ana -> User band use them to produce anUser b. Given that the function takes anavalue, the first thing to try is looking for anavalue to pass to it. We do have such a value: the one wrapped by theAgeconstructor in theUser avalue:To write a
Monadinstance 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
Usercontext 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.