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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With