purescript-contrib / purescript-quickcheck-laws

QuickCheck powered law tests for PureScript's core typeclasses.
MIT License
25 stars 18 forks source link

Distributitivity of MonadPlus instance for Maybe #7

Closed DavidHarrison closed 8 years ago

DavidHarrison commented 9 years ago

The tests brings up the following example:

x = Just (false)
y = Just (true)
x >>= f = Nothing
y >>= f = Just ("")

in the distributivity law for MonadPlus:

((x <|> y) >>= f) == ((x >>= f) <|> (y >>= f))

which evaluates to:

Nothing == Just ("")
DavidHarrison commented 9 years ago

Also brought up by the tests is:

x = Just ("")
mempty <> x = Nothing

for the left identity law of Monoid:

mempty <> x == x

If I understand correctly, (<>) and (<|>) are the same for Maybe.

paf31 commented 9 years ago

mempty should be Just mempty for Maybe. Is it not?

Sent from my iPhone

On Jul 5, 2015, at 6:31 PM, David Harrison notifications@github.com wrote:

Also brought up by the tests is:

x = Just ("") mempty <> x = Nothing for the left identity law of monoid:

mempty <> x == x If I understand correctly, (<>) and (<|>) are the same for Maybe.

— Reply to this email directly or view it on GitHub.

DavidHarrison commented 9 years ago

purescript-maybe defines Monoid as:

instance monoidMaybe :: (Semigroup a) => Monoid (Maybe a) where
  mempty = Nothing

Changing that would resolve the issue for monoids, though I'm not sure how it works with McBride's view of the instance, the current behavior for the First wrapper in Haskell, which has the monoid instance:

instance Monoid (First a) where
        mempty = First Nothing
        First Nothing `mappend` r = r
        l `mappend` _             = l

For the MonadPlus instance, Haskell has the same behaviour. It seems that MonadPlus for Maybe and IO do not satisfy Left Distribution, but instead Left Catch.

hdgarrood commented 9 years ago

If we had mempty = Just mempty, then we'd need a stronger constraint of Monoid a for the Monoid (Maybe a) instance. That's not necessarily a problem but I would like to have some way of making a Semigroup (which is not a Monoid) into a Monoid by adding an extra element to act as the identity.

hdgarrood commented 9 years ago

Also: shall we add tests from purescript-quickcheck-laws to the tests of libraries like purescript-maybe, so that we don't get caught out by things like these again?

garyb commented 9 years ago

We can't do that without introducing circular dependencies. @paf31 and I have argued a bit over that in the past, as to me, devDependencies aren't real dependencies, but you do need a slight hack of having to delete purescript-maybe from bower_components after bower installing.

Alternatively you need a separate test project inside this project, with its own bower.json, but then it's a hassle to keep things up to date between both sets of dependencies, etc. It's probably less bad now we're using npm scripts to do build stuff, but I dunno.

hdgarrood commented 9 years ago

aww yeah: purescript/purescript-maybe#13

garyb commented 8 years ago

Looks like we fixed this at some point, I think by changing (<|>).