I'm trying to set an authorization scheme where I check that 1. user is logged in 2. user has access to a certain object. For this I first call maybeAuthId
, then try to get the current object, and 'join' to another table which lists permissions. There are two levels of maybe-cases and one level of empty-list case. I thought of using MaybeT, but either I'm too tired to get it to work or the "not really monad transformer"-handler-transformers can't be used with MaybeT. Is there a nice way to handle deep maybes?
Edit:
I was a bit unclear it seems. I meant that I have something like this:
case foo of
Nothing -> something
Just foo' -> do
bar <- somethingelse
case bar of
Nothing -> ...
Just bar' -> ...
It's not exactly clear what you mean by "handle deep maybes", but you can use monadic
join
(fromControl.Monad
) to remove one level of nesting at a time.Using MaybeT is probably a better fit for your problem, though. If you clarify what you're trying to do, we could help you formulate it with MaybeT.
From what I understand, your layers look like:
... and you want to
join
the twoMaybe
s together, but the list is in the way. This is precisely the problemsequence
solves:Note that if we specialize
sequence
to theMaybe
monad we get:In this particular case,
sequence
will return aNothing
if there is at least oneNothing
in the list, but if they are allJust
s, then it will join them all into a singleJust
.All that remains is to map
sequence
over the outerMaybe
:Now this is exactly in the form we need for join:
So, intuitively, what the above function does is that if all the inner
Maybe
s areJust
s and the outerMaybe
is aJust
, then it fuses the entire result into a singleJust
containing the list. However, if anyMaybe
(either the inner ones or outer one) is aNothing
, the final result is aNothing
.Notice that despite doing a bunch of blind type-chasing, we ended up with a function that intuitively does the right thing. This is the power of abstractions grounded in category theory.
You can totally use
MaybeT
for Yesod. Just do it like this:As you said, most functions aren't optimized for generic error handling in Yesod. However, if you have something of the form
Monad m => m (Maybe a)
, you can simply useMaybeT
to turn it inside out intoMonad m => Maybe (m a)
.