From the example of Validation (https://hackage.haskell.org/package/Validation), I'm trying to get an intuition of detecting how/why an applicative could not be a Monad (Why can AccValidation not have a Monad instance?)
Could you challenge my reasoning ?
I think about a monad in the way we handle behind the join (m ( m b) -> m b), let's develop my understanding with an example like Validation:
in data Validation err a
, the functor structure is (Validation err). When you look at the definition of the bind for Monad and specializing the types for Validation you get the following :
(>>=) :: m a -> (a -> m b) -> m b
(>>=) :: (Validation err) a -> ( a -> (Validation err) b) -> (Validation err) b
if you beta reduce (>>=) you'll get :
m a -> (a -> m b) -> m b // if we apply (m a) in the monadic function
m ( m b) -> m b
then to get the result of (>>=) which is m b, you'll use join :
join :: (Monad m) => m (m a) -> m a
join x = x >>= id
If you play with the types you'll get :
join m ( m b ) = m ( m b) >>= (\(m b) -> m b -> m b) which gives m b
So that join just drop the outermost structure, only the value in the innermost type (the value of the innermost functor) is kept/transmitted through the sequence.
In a monad we can't pass some information from the functor structure (e.g Validation err) to the next 'action', the only think we can pass is the value. The only think you could do with that structure is short-circuiting the sequence to get information from it.
You can't perform a sequence of action on the information from the functor structure (e.g accumulating something like error..)
So I would say that an applicative that is squashing its structure with some logic on its structure could be suspicious as not being able to become a Monad ?
join
doesn't merely drop the outer layer; it merges it with the inner layer. – duplodeIO
? Once you perform the outerIO
computation to "get information from it", there is no turning back -- no way to undo or otherwise discard it. – duplode