Is it acceptable if Applicative behave not like a Monad

Hello, I have such a question: assume you have some type `T` which has Applicative and Monad instances. Is it ok if code like this: foo :: Int -> T String bar :: Int -> T Int (,) <$> foo 10 <*> bar "20" behaves not like this code: foobar = do x <- foo 10 y <- bar "20" return (x, y) The word "behaves" I mean not just returning value but the effect performed also.

Yes it's okay and sometimes expected for them not not behave the same, but
see e.g. haxl and ApplicativeDo.
For example, the applicative version may run foo and bar in parallell. But
using monad they run sequentially.
- Adam
On Thu, Apr 30, 2015 at 5:45 PM, Alexey Uimanov
Hello, I have such a question: assume you have some type `T` which has Applicative and Monad instances. Is it ok if code like this:
foo :: Int -> T String bar :: Int -> T Int
(,) <$> foo 10 <*> bar "20"
behaves not like this code:
foobar = do x <- foo 10 y <- bar "20" return (x, y)
The word "behaves" I mean not just returning value but the effect performed also.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

On Thu, Apr 30, 2015 at 10:49 PM, Adam Bergmark
Yes it's okay and sometimes expected for them not not behave the same, but see e.g. haxl and ApplicativeDo.
This is a value of okay I've never seen before.
For example, the applicative version may run foo and bar in parallell. But using monad they run sequentially.
What if pure weren't a perfect synonym for return? What if the methods of the semigroup instance didn't match those of the monoid? The mind boggles at the confusion that would result. Such cases typically call for newtypes to sort out the effect classes. -- Kim-Ee

I'm afraid I have to disagree with Adam as well. Recently I've triggered a
prolonged discussion on exactly the subject (
https://github.com/ekmett/either/pull/38). Being originally convinced that
the instances can behave however it fits, I think I've been over-persuaded
in the end.
Shortly speaking, while I can't say I like it, the rule seems to be that
`<*>` should produce the same side effects as Monad's `ap`.
The most convincing argument I've seen so far against the two digressing is
that it can cause unexpected behaviour of the "do" notation (
https://github.com/ekmett/either/pull/38#issuecomment-95695814), but you'll
find plenty of other arguments in the discussion as well.
Best regards,
Nikita Volkov
2015-04-30 19:07 GMT+03:00 Kim-Ee Yeoh
On Thu, Apr 30, 2015 at 10:49 PM, Adam Bergmark
wrote: Yes it's okay and sometimes expected for them not not behave the same, but see e.g. haxl and ApplicativeDo.
This is a value of okay I've never seen before.
For example, the applicative version may run foo and bar in parallell. But using monad they run sequentially.
What if pure weren't a perfect synonym for return?
What if the methods of the semigroup instance didn't match those of the monoid?
The mind boggles at the confusion that would result.
Such cases typically call for newtypes to sort out the effect classes.
-- Kim-Ee
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

On Thu, Apr 30, 2015 at 1:32 PM, Nikita Volkov
I'm afraid I have to disagree with Adam as well. Recently I've triggered a prolonged discussion on exactly the subject ( https://github.com/ekmett/either/pull/38). Being originally convinced that the instances can behave however it fits, I think I've been over-persuaded in the end.
Shortly speaking, while I can't say I like it, the rule seems to be that `<*>` should produce the same side effects as Monad's `ap`.
One example of a library where the Applicative and Monad instances mismatch is uu-parsinglib. http://stackoverflow.com/questions/18275123/cannot-compute-minimal-length-of... There's a good reason the library is this way but the behavior can be rather startling.

Why can't the library provide a `newtype`, one which supports `Applicative`
*and* `Monad` interfaces (where the applicative and monadic interfaces
match), and an un-newtyped variant that only supports `Applicaative`, as
well as conversion functions?
I think this would be clearer, as it would force you to switch into
"Monad"-mode purposefully, and the documentation on the conversion function
can make very clear what is going on.
I agree that, now that we have AMP, applicative and monadic interfaces
absolutely *should* match, and that it should be considered an error for
them not to; semantically different interfaces can be provided with
newtypes.
-- Andrew
On Thu, Apr 30, 2015 at 6:46 PM, Omari Norman
On Thu, Apr 30, 2015 at 1:32 PM, Nikita Volkov
wrote: I'm afraid I have to disagree with Adam as well. Recently I've triggered a prolonged discussion on exactly the subject ( https://github.com/ekmett/either/pull/38). Being originally convinced that the instances can behave however it fits, I think I've been over-persuaded in the end.
Shortly speaking, while I can't say I like it, the rule seems to be that `<*>` should produce the same side effects as Monad's `ap`.
One example of a library where the Applicative and Monad instances mismatch is uu-parsinglib.
http://stackoverflow.com/questions/18275123/cannot-compute-minimal-length-of...
There's a good reason the library is this way but the behavior can be rather startling.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

On Thu, Apr 30, 2015 at 10:11:49PM -0700, Andrew Gibiansky wrote:
Why can't the library provide a `newtype`, one which supports `Applicative` *and* `Monad` interfaces (where the applicative and monadic interfaces match), and an un-newtyped variant that only supports `Applicaative`, as well as conversion functions?
This sounds like the right solution to me.

If you don't mind your users wishing you death when they code breaks when they combine applicative style with do notation like: foo <- bar <$> baz <*> qux then sure, go ahead. Seriously, though, Andrew Gibiansky is right, use a newtype. Best regards, Marcin Mrotek

On Thu, Apr 30, 2015 at 10:11:49PM -0700, Andrew Gibiansky wrote:
I agree that, now that we have AMP, applicative and monadic interfaces absolutely *should* match, and that it should be considered an error for them not to; semantically different interfaces can be provided with newtypes.
This requirement is in the documentation for both Applicative and Monad classes. (It's been in Applicative since 2010, and was added to Monad in the AMP release.)

My message was written too hastily, sorry about that.
The example Alexey asked is exactly what the ApplicativeDo proposal[1] uses
as motivation. The point of it is that you shouldn't need to care about
writing applicative or do-style, when the behavior differs the most
efficient one can be used.
Though as it stands the proposal seems to run into the problem of being
unintuitive like others mentioned since you need to enable an extension. A
type implementing this functionality would need to be documented as
"Enable ApplicativeDo when using this, or be very confused"
[1] https://ghc.haskell.org/trac/ghc/wiki/ApplicativeDo
- Adam
On Fri, May 1, 2015 at 2:00 PM, Ross Paterson
I agree that, now that we have AMP, applicative and monadic interfaces absolutely *should* match, and that it should be considered an error for
On Thu, Apr 30, 2015 at 10:11:49PM -0700, Andrew Gibiansky wrote: them
not to; semantically different interfaces can be provided with newtypes.
This requirement is in the documentation for both Applicative and Monad classes. (It's been in Applicative since 2010, and was added to Monad in the AMP release.) _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe

As usual, it depends on what aspects of behavior you consider important. As
an obvious example, if the two produce (or store) distinct structures that
are (==), that should be fine. Similarly, if the effects are different in a
way that does not matter to your application (e.g., one may buffer more
input than the other, or they may read from the same files in different
orders, or they may produce the same images on screen using different
graphics operations) then that should be fine too.
On Apr 30, 2015 11:45 AM, "Alexey Uimanov"
Hello, I have such a question: assume you have some type `T` which has Applicative and Monad instances. Is it ok if code like this:
foo :: Int -> T String bar :: Int -> T Int
(,) <$> foo 10 <*> bar "20"
behaves not like this code:
foobar = do x <- foo 10 y <- bar "20" return (x, y)
The word "behaves" I mean not just returning value but the effect performed also.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe
participants (10)
-
Adam Bergmark
-
Alexey Uimanov
-
Andrew Gibiansky
-
David Feuer
-
Kim-Ee Yeoh
-
Marcin Mrotek
-
Nikita Volkov
-
Omari Norman
-
Ross Paterson
-
Tom Ellis