Skip to content

Interplay between Apply and Bind #158

New issue

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

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

Already on GitHub? # to your account

Closed
joneshf opened this issue Feb 4, 2018 · 4 comments · Fixed by #229
Closed

Interplay between Apply and Bind #158

joneshf opened this issue Feb 4, 2018 · 4 comments · Fixed by #229

Comments

@joneshf
Copy link
Member

joneshf commented Feb 4, 2018

On the heels of #141, we now have that the Apply and Bind instances for a data type have to agree when that data type also has a Monad. It seems like we're still missing something.

With the laws as they're written, you can have a Bind instance for a data type that doesn't agree with its Apply instance, so long as said data type does not also define a Monad instance. I think that's not right. I think we want to make sure that the Apply and Bind instances agree.

A real data type that could sneak a lawful Bind instance in as the laws are now is Data.Validation.Semigroup.V:

instance bindV :: (Semigroup a) => Bind (V a) where
  bind = flip (unV invalid)

I'm pretty sure that definition is associative, but it will "short-circuit" at the first invalid case. That doesn't agree with the Apply instance (which accumulates invalid cases).

I'm proposing that we change ap to something like:

ap :: forall a b f. Bind f => f (a -> b) -> f a -> f b
ap f a = bind f (mapFlipped a)

And move the Applicative Superclass law to Bind (probably change the name of the law as well).

Thoughts?

@garyb
Copy link
Member

garyb commented Feb 4, 2018

I think maybe the situation as it is is correct? As long as there is no Monad instance, there is no specific behaviour determined for the interaction between Bind and Applicative. I don't know, maybe that's a bit of a cheat.

If we did move the Applicative Superclass law to bind, we'd also have to include "when also applicative" or something, which also doesn't seem right given it's not mentioned in the types/class anywhere.

@joneshf
Copy link
Member Author

joneshf commented Feb 4, 2018

The problem isn't between Applicative and Bind. It's between Apply and Bind. We can (should?) relax the constraint from Monad to Bind since you don't need Applicative in order to derive an implementation for apply. Our current implementation for ap is overconstrained.

The identity laws for Monad are what talk about the interplay between Applicative and Bind? I hypothesize that the Applicative Superclass law (as it's written currently with ap requiring Monad f) subsumes at least one of the identity laws.

@hdgarrood
Copy link
Contributor

Took me a while to get around to reading this but yes, I'm totally in favour.

@eric-corumdigital
Copy link

I agree with this idea. It does not make sense to have Bind imply Apply yet not lawfully have an equivalence between bind and apply.

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

Successfully merging a pull request may close this issue.

4 participants