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

Why doesn't Future implement the Alternative interface by default? #290

Closed
gwn opened this issue Oct 20, 2018 · 2 comments
Closed

Why doesn't Future implement the Alternative interface by default? #290

gwn opened this issue Oct 20, 2018 · 2 comments

Comments

@gwn
Copy link

gwn commented Oct 20, 2018

I don't want to rely on Future specific methods such as race and parallel when there are lovely generic alternatives such as alt, traverse etc..

I'm asking this question because my understanding of the "time-dependent applicatives" is limited; as I'm new to functional programming.

I came across the following explanation in the README of the concurrify library:

Most time-dependent applicatives are very useful as Monads, because it gives them the ability to run sequentially, where each step depends on the previous. However, they lose the ability to run concurrently. This library allows one to wrap a Monad (with sequential ap) in an Alternative (with parallel ap).

I infer from the explanation above that Future doesn't have concurrent behavior by default whether we use it as a monad or an applicative. Why is this the case? Is this the canonical implementation of this type (if there is such a thing)?

What is preventing me from using ConcurrentFuture all the time instead of a Future? Is the sequential approach more performant / lightweight / safe / simple by default or something like that?

Can't we get sequential behavior in ConcurrentFuture too if we use it as a monad?

I apologize for my ignorance on the topic. I feel that these questions are probably not really about Fluture. I'm just looking for quick pointers instead of in-depth explanations about the nature of these types and related laws.

@Avaq
Copy link
Member

Avaq commented Oct 21, 2018

Hi @gwn.

I apologize for my ignorance on the topic. I feel that these questions are probably not really about Fluture.

There is no need for that. It's a very good question - or, several questions, rather. And Fluture is a good place to ask them: it's a prominent implementation of a time-dependent Applicative.

What is preventing me from using ConcurrentFuture all the time[?]

Practically, because it doesn't have Monad, so you cannot use chain on it.

Can't we get sequential behavior in ConcurrentFuture too if we use it as a monad?

If we would implement Monad on ConcurrentFuture, the implementation of Applicative must become sequential. That would mean ConcurrentFuture is no longer concurrent. ;)

Background: In case a type has Monad, the Applicative instance must behave as if derived from chain. This means that if the type doesn't have sequential behavior in ap (as dictated by the sequential nature of chain), it's not a valid Monad. Ergo, time-dependent Monads have sequential ap. For further reading: fantasyland/fantasy-land#179.

Why doesn't Future implement the Alternative interface by default?

I believe it has to do the way the Applicative instance is affected in conflicting ways by the Monad or Alternative instance on time-dependent types. The way I've come to understand it, implementing both Monad and Alternative on a time-dependent Applicative, would mean that there are then two conflicting yet valid implementations of Applicative which the type must implement. Though now that you ask, I can't really back that up.

Up until this point, I had assumed that the conflict arises from the Alternative instance dictating the behavior of ap in a similar -but conflicting- way to how Monad affects it's behavior. However, looking into it and reading through the Fantasy Land spec again, I can't seem to find any proof if this.

I currently cannot provide a good reason as to why Future can't have Alternative as well as Monad - be it with sequential ap, so you'd still need a wrapper type to get parallelism in your sequence.

I would like to ask @safareli for some input here. Intuitively, it seems logical to me that a type is either fully sequential, or fully parallel. But I don't see any mention of the relationship between Alternative and Applicative that would make that apparent.

@gwn
Copy link
Author

gwn commented Oct 23, 2018

Ah. Thank you for the great explanation, @Avaq. You really made everything clear.

I examined the issue you referred to and all other related issues -as well as the ones from Fantasy Land and other future libraries- and now have an understanding of the matter, which I realized to be a bit complicated. (Makes me happy as it shows that my question is not a silly one indeed :)

I'm convinced for now that the separate types approach makes sense, so I'll happily make do with ConcurrentFuture for my algebraic needs.

Closing this; though further input will of course be appreciated.
: )

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

2 participants