Hi Olumide,
Let the types help you out.
The Monad typeclass (omitting the superclass constraints):
class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
Write out the specialised type signatures for (->) r:
{-# LANGUAGE InstanceSigs #-}
-- This extension allows you to specify the type signatures in instance declarations
instance Monad ((->) r) where
return :: a -> (r -> a)
(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b)
Now we look at how to make some definition of return that type checks. We're given an a and we want to return a function that takes an r and returns an a. Well the only way you can really do this is ignoring the r and returning the value you were given in all cases! Because 'a' can be *anything*, you really don't have much else you can do! Hence:
return :: a -> (r -> a)
return a = \_ -> a
Now let's take a look at (>>=). Since this is a bit complicated, let's work backwards from the result type. We want a function that gives us a b given an r and given two functions with types (r -> a) and (a -> (r -> b)). To get a b, we need to use the second function. To use the second function, we must have an a, which we can get from the first function!
(>>=) :: (r -> a) -> (a -> (r -> b)) -> (r -> b)
(>>=) f g = \r -> (g (f r)) r
Hope that helps!
Rahul