Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any intuition to understand join two functions in Monad?

join is defined along with bind to flatten the combined data structure into single structure.

From type system view, (+) 7 :: Num a => a -> a could be considered as a Functor, (+) :: Num a => a -> a -> a could be considered as a Functor of Functor, how to get some intuition about it instead of just relying on type system? Why join (+) 7 === 14?

Even though it is possible to get the final result through manually stepping by the function binding process, it would be great if some intuition were given.

This is from the NICTA exercises.

-- | Binds a function on the reader ((->) t).
--
-- >>> ((*) =<< (+10)) 7
-- 119
instance Bind ((->) t) where
  (=<<) ::
    (a -> ((->) t b))
    -> ((->) t a)
    -> ((->) t b)
  (f =<< a) t =
    f (a t) t

-- | Flattens a combined structure to a single structure.
--
-- >>> join (+) 7
-- 14
join ::
  Bind f =>
  f (f a)
  -> f a
join f =
  id =<< f

*Course.State> :t join (+)
join (+) :: Num a => a -> a
*Course.State> :t join
join :: Bind f => f (f a) -> f a
*Course.State> :t (+)
(+) :: Num a => a -> a -> a
like image 307
Kamel Avatar asked Sep 01 '15 04:09

Kamel


1 Answers

how to get some intuition about it instead of just relying on type system?

I'd rather say that relying on the type system is a great way to build a specific sort of intuition. The type of join is:

join :: Monad m => m (m a) -> m a

Specialised to (->) r, it becomes:

(r -> (r -> a)) -> (r -> a)

Now let's try to define join for functions:

-- join :: (r -> (r -> a)) -> (r -> a)
join f = -- etc.

We know the result must be a r -> a function:

join f = \x -> -- etc.

However, we do not know anything at all about what the r and a types are, and therefore we know nothing in particular about f :: r -> (r -> a) and x :: r. Our ignorance means there is literally just one thing we can do with them: passing x as an argument, both to f and to f x:

join f = \x -> f x x

Therefore, join for functions passes the same argument twice because that is the only possible implementation. Of course, that implementation is only a proper monadic join because it follows the monad laws:

join . fmap join = join . join
join . fmap return = id
join . return = id

Verifying that might be another nice exercise.

like image 85
duplode Avatar answered Sep 22 '22 06:09

duplode