Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is there a reason for no MonadFail instance? #306

Open
luke-clifton opened this issue Aug 21, 2023 · 4 comments
Open

Is there a reason for no MonadFail instance? #306

luke-clifton opened this issue Aug 21, 2023 · 4 comments

Comments

@luke-clifton
Copy link

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?

@reubenharry
Copy link
Contributor

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.

@luke-clifton
Copy link
Author

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

@turion
Copy link
Collaborator

turion commented Aug 28, 2023

[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.

@luke-clifton
Copy link
Author

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants