Skip to content

Delete unlawful MonadPlus instance #97

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

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ deleteBlankLines path = do

This looks like ordinary, synchronous, imperative code, but actually operates asynchronously without any callbacks. Error handling is baked in so you only deal with it when you want to.

The library contains instances for `Semigroup`, `Monoid`, `Apply`, `Applicative`, `Bind`, `Monad`, `Alt`, `Plus`, `MonadPlus`, `MonadEff`, and `MonadError`. These instances allow you to compose asynchronous code as easily as `Eff`, as well as interop with existing `Eff` code.
The library contains instances for `Semigroup`, `Monoid`, `Apply`, `Applicative`, `Bind`, `Monad`, `Alt`, `Plus`, `MonadEff`, and `MonadError`. These instances allow you to compose asynchronous code as easily as `Eff`, as well as interop with existing `Eff` code.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this list doesn't contain MonadZero

Copy link
Author

@no-longer-on-githu-b no-longer-on-githu-b Apr 6, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nor any of Parallel, MonadRec, Alternative, and Functor.


## Escaping Callback Hell

Expand Down
4 changes: 1 addition & 3 deletions src/Control/Monad/Aff.purs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import Control.Monad.Eff.Class (class MonadEff)
import Control.Monad.Eff.Exception (Error, EXCEPTION, throwException, error)
import Control.Monad.Error.Class (class MonadThrow, class MonadError, throwError)
import Control.Monad.Rec.Class (class MonadRec, Step(..))
import Control.MonadPlus (class MonadZero, class MonadPlus)
import Control.MonadZero (class MonadZero)
import Control.Parallel (class Parallel)
import Control.Plus (class Plus, empty)

Expand Down Expand Up @@ -198,8 +198,6 @@ instance alternativeAff :: Alternative (Aff e)

instance monadZero :: MonadZero (Aff e)

instance monadPlusAff :: MonadPlus (Aff e)

instance monadRecAff :: MonadRec (Aff e) where
tailRecM f a = runFn3 _tailRecM isLoop f a
where
Expand Down
15 changes: 15 additions & 0 deletions test/Test/Main.purs
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,18 @@ test_syncTailRecM = do
pure (Done 0)
go { n, v } = pure (Loop { n: n - 1, v })

test_monadPlusBad :: TestAVar Unit
test_monadPlusBad = do
let f true = throwError (error "error")
f false = pure unit
either (const $ log "Success: f throws regardless")
(const $ log "Failure: f does not throw")
=<< attempt ((pure true <|> pure false) >>= f)
either (const $ log "Failure: f exception not caught")
(const $ log "Success: f exception is caught")
=<< attempt ((pure true >>= f) <|> (pure false >>= f))
pure unit

loopAndBounce :: forall eff. Int -> Aff (console :: CONSOLE | eff) Unit
loopAndBounce n = do
res <- tailRecM go n
Expand Down Expand Up @@ -338,6 +350,9 @@ main = do
log "Testing synchronous tailRecM"
test_syncTailRecM

log "Testing that MonadPlus instance would not be lawful"
test_monadPlusBad

log "pre-delay"
delay (Milliseconds 1000.0)
log "post-delay"
Expand Down