monad-bayes
monad-bayes copied to clipboard
Is there a reason for no MonadFail instance?
Sometimes it would be neat to be able to use a fallible pattern match in do
-notation, similar to what we get with lists. This is enabled by having a MonadFail
instance.
I was wondering if there was some reason why there is no MonadFail
instance available that I can not see?
No reason that comes to mind, although do you have a specific example use case in mind? I've certainly used an ExceptT transformer to a similar effect.
It just seems kinda neater in some scenarios. Especially if the sampling is abstracted and we can't "fix" it at the source.
enumerator $ do
a <- uniformD [Just 1, Just 2, Nothing]
condition (isJust a)
pure a
enumerator $ do
Just a <- uniformD [Just 1, Just 2, Nothing]
pure a
[lengthy comment following] Your two examples even have different types, the first being MonadMeasure m => m (Maybe Int)
, the second being MonadMeasure m => m Int
. Which is more attractive because we know that only the Just
path has nonzero measure, and the Nothing
path cannot enter any observable in the end.
To achieve that effect, one would like to write:
enumerator $ do
aMaybe <- uniformD [Just 1, Just 2, Nothing]
case aMaybe of
Just a -> pure a
Nothing -> do
score 0
error "Impossible"
But unfortunately, there is no law in MonadScore
that prevents anything after 0 score to be unreachable, i.e. a law like score 0 >> ma = score 0
. Such a law should hold approximately in any reasonable probability monad, I believe, but I'm not sure it is mentioned anywhere in the original article. I don't know the literature on probability monads well enough to say whether this is a common law. Anyways it is not enforced in the implementations.
I read your proposal as adding such a possibility to the interface via MonadFail
. The semantic of fail
is supposed to mean "don't continue traversing this branch", like mzero
.
Yes, the types being different was a transcription error.
And yes, I had noticed that condition
was not quite the same as guard
in the Enumerator
type, in exactly the way you describe. The computation doesn't "stop" with condition. That was going to be a follow up question. (In fact, when I want to use Enumerator
I often use guard
instead of condition
for that reason and it seems to work as expected).
So your conclusion is correct, I'd actually like to have a Alternative
(and possibly MonadPlus
) instance to go along with the MonadFail
instance. These (bar MonadFail
) are there for Enumerator
which I do find useful, but then can't use when I want to use a different probability monad.