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

reduce data type fragmentation #139

Open
davidchambers opened this issue Nov 29, 2016 · 21 comments
Open

reduce data type fragmentation #139

davidchambers opened this issue Nov 29, 2016 · 21 comments

Comments

@davidchambers
Copy link
Member

Related to #105

Once sanctuary-js/sanctuary-either#1 and sanctuary-js/sanctuary-maybe#1 are resolved (within the next two months I hope) I think we should do the following:

  • remove the Either type from RF (in favour of sanctuary-either);
  • remove the Maybe type from RF (in favour of sanctuary-maybe); and
  • remove the Future type from RF (in favour of Fluture).

Reducing the number of different implementations of these (and other) data types is good for interoperability and thus good for the community. @SimonRichardson has been making this point for years.

@buzzdecafe
Copy link
Member

fine with me, i am ready to retire 😄

@TheLudd
Copy link
Contributor

TheLudd commented Nov 30, 2016

While Fluture seems much more mature and complete than our Future I wouldn't want to switch unless it has parallel execution in ap.

And with that being said, if you look at promises you have libraries like q, bluebird, when, promise and now native promises. While ramda fantasy may not become the rock solid foundation of functional programming in JavaScript I see no need to remove anything just because other versions exist elsewhere.

@davidchambers
Copy link
Member Author

While Fluture seems much more mature and complete than our Future I wouldn't want to switch unless it has parallel execution in ap.

According to fantasyland/fantasy-land#179 a Monad's fantasy-land/ap method must execute sequentially in order to be lawful. My understanding of this matter is not strong.

And with that being said, if you look at promises you have libraries like q, bluebird, when, promise and now native promises.

Yes, we do. Multiple incompatible implementations with subtly (or in some cases not so subtly) different semantics. We've replicated this unfortunate situation with our algebraic data types. 😢

While ramda fantasy may not become the rock solid foundation of functional programming in JavaScript I see no need to remove anything just because other versions exist elsewhere.

I see several reasons:

  • Someone who wants to use the Maybe data type for the first time must first decide which of the many implementations to use. This may lead to indecision, increasing the likelihood that the user will decide to stick with Nullable and null checks.

  • When there are several implementations of a data type we end up defining natural transformations from one to another, such as eitherToEither. Any library which exports a function of a type such as String -> Maybe Number is really exporting a function of a type such as String -> RamdaFantasyMaybe Number. The values returned by such functions may be incompatible, so natural transformations may be necessary to use functions from different libraries together. By decreasing interoperability we're encouraging library authors to export functions of unsafe types such as String -> Nullable Number.

  • Duplicated effort. This has been discussed in Take Sanctuary #105, so I won't add much here. I would like to acknowledge my part in the problem. I have a history of creating new projects rather than contributing to existing projects. I have worsened the situation in this respect. The Haskell community, on the other hand, seems more collaborative. I've encountered several Haskell projects which are ten or fifteen years old and have been passed from one maintainer to another several times.

@TheLudd
Copy link
Contributor

TheLudd commented Nov 30, 2016

According to fantasyland/fantasy-land#179 a Monad's fantasy-land/ap method must execute sequentially in order to be lawful.

This is bad news because from my experience, this will make the future type practically unusable.

This will lead to helper functions such as "parallel" to be used instead of just lift and sequence. That might not be so bad if you are working with just Futures instances but once you want to put the Future inside a transformer much of the beauty and simplicity that comes from the types is lost.

With a parallel ap you can do parallel processing and sequential processing by using functions that are applicable to all modad types. But my understanding of why this is not lawful is also not very great.

@davidchambers
Copy link
Member Author

This strikes me as a valid concern, @TheLudd. Let's raise the issue with all N of the JavaScript Future/Task library maintainers. 😜

@TheLudd
Copy link
Contributor

TheLudd commented Nov 30, 2016

Seems to be more of an issue to raise with the specification people. Any maintainer can then choose to be lawful or not... =)

Meanwhile, I will listen to this... https://www.youtube.com/watch?v=9RHLY0xbA28

@TheLudd
Copy link
Contributor

TheLudd commented Nov 30, 2016

But I did interpret this comment as if there was a possibility of parallelism.

@SimonRichardson
Copy link

Any maintainer can then choose to be lawful or not... =)

As long as they tell people that, then it seems reasonable.

@TheLudd
Copy link
Contributor

TheLudd commented Nov 30, 2016

@SimonRichardson To clarify:
I understood @davidchambers to mean that we (unfortunately) need to discuss this across many repos and maintainers since we have this problem of spread out implementations. I merely suggested that the discussion belongs in the specification, i.e. one repository.

@safareli
Copy link
Contributor

But I did interpret this comment as if there was a possibility of parallelism.

Discussion in the referenced comment was on Alternative instance not Applicative.

@safareli
Copy link
Contributor

also there could be non monadic Futures (Applicative) which are as parallel as possible. you can mix then in a lawful way using Concurrent like structure from safareli/free#31

@scott-christopher
Copy link
Member

If we are to remove Maybe, Either and Future, then I'd suggest we should consider closing Ramda Fantasy in full.

Should we perhaps also consider removing the Either and Maybe from Sanctuary and promote the existing Fantasy Land equivalent packages? Or perhaps just provide sanctuary-def wrappers for the FL implementations instead?

The advantages of promoting the types under the FL banner is that we can then potentially refer to Maybe and Either in the FL spec, without the having to dance around wording or introduce types like we did for ChainRec.

@davidchambers
Copy link
Member Author

Should we perhaps also consider removing the Either and Maybe from Sanctuary and promote the existing Fantasy Land equivalent packages?

Merging the Sanctuary implementations into their respective fantasy-land packages sounds good to me. I'm happy to do this if @SimonRichardson and the rest of the fantasy-land team are happy for me to maintain these projects.

The advantages of promoting the types under the FL banner is that we can then potentially refer to Maybe and Either in the FL spec, without the having to dance around wording or introduce types like we did for ChainRec.

This would be wonderful!

@safareli
Copy link
Contributor

safareli commented Dec 1, 2016

that would be amazing +1

@SimonRichardson
Copy link

SimonRichardson commented Dec 1, 2016 via email

@svozza
Copy link

svozza commented Dec 2, 2016

Very exciting!

@CrossEye
Copy link
Member

CrossEye commented Dec 3, 2016

While I would have no problem shuttering Ramda-Fantasy, I'm not in agreement with the wider point here.

Ramda itself was a learning exercise at first. @buzzdecafe and I used it and its predecessor to learn more about techniques we had had limited exposure to in other languages and wanted to see used in JS. But Ramda quickly grew beyond that and turned into a community-focused library. R-F I also saw as a way to learn more about what folks were doing with FantasyLand. But I don't think it ever turned into as serious an effort. (Perhaps my perspective is off; I never became very engaged with R-F.) I don't think it would be a big blow to lose it.

But I don't buy this at all:

Reducing the number of different implementations of these (and other) data types is good for interoperability and thus good for the community.

I believe this is good for a community only for a short time. The whole point of a specification like FantasyLand is that it specifies exactly how certain things can interoperate. But it leaves wide open the remainder of their design. This allows implementations to play around in the solution space and come up with many different designs, many competing philosophies, many implementations that choose varying trade-offs. When we settle on a single version, we lose sight of the fact that the decisions made by that version are not necessarily optimal, that there might be better ones for one's situation or even for the wider community. It's especially problematic if we settle early.

I don't know if anyone else came through the Java Web world, but I spent too much time there, and I saw this problem several times: mostly imposed systems like EJBs and more organic ones like Struts: both were pretty horrible technologies that happened to gain just enough traction at just the right time to become nearly unstoppable for years. Competitors to these did not have a chance for a very long time. If you weren't using these, you were doing something wrong.

This is the same reason that I'm very happy to have Sanctuary and Ramda coexist with very distinct, but overlapping ideas. And it's why I was very sorry to see fn.js totter and FKit disappear. I think we're made much stronger with a marketplace of concepts, of implementations, of philosophies.

When I've reached for a F-L implementation, I've sometimes pulled down Ramda Fantasy, but I've been more likely to use Folktale. I haven't yet used Fluture, but I keep hearing good things, so I'll probably grab that next time. I think these separate tools help spur one another to innovate; they inform one another about performance, about API design, about documentation, about the entire software lifecycle. This is a good thing. A very good thing.

I would resist dropping R-F, except that I think there are plenty of good alternatives. If it's being actively maintained, and people are interested in participating, by all means, keep it running. But with a thriving community, there's no reason to bother unless people really want to use it.

@safareli
Copy link
Contributor

safareli commented Dec 3, 2016

the problem I see, is that there are not so many maintainers and I think most of FL implementations are outdated (or are not lawful: some optionals are not Functors, and some tasks, are ignore ap=<*> law), if we agree on some specific implementations and work on them, we could at least have some implementations which are always up to date, maintained, tested and are lawful, which is better than what we we have today. once community groves there could pop other implementations as well, which also fine.

@scott-christopher
Copy link
Member

there are not so many maintainers

I don't think that's necessary true, nor a problem

most of FL implementations are outdated

That's true in regards to the current version of FL, but that's also why versioning in FL was introduced (despite RF still adopting the pre-versioning version)

some optionals are not Functors

I'd be interested to see an example of this

some tasks, are ignore ap=<*> law

I don't see that law defined anywhere in FL, nor do I think it's actually necessary. This would suggest that if an implementation can be derived then it must be, rather than being able to use a more optimal one, despite both choices evaluating to the same value.

That said, I think I'm still in favour for combining efforts towards a single implementation for simple data types. There could still be room for competing implementations if the data-type defined in FL was kept to a "minimum viable data-type" that just implemented the constructors, deconstructors of some kind and the FL spec. This would allow existing libraries to implement any various supporting libraries that they wished to while keeping the core data-type reusable across libraries.

If we were to consolidate efforts and promote the use of the FL data types, I would like to see a greater effort placed on documentation and discovery of the data types. Whether that's through a simple website that linked to (or displayed) the spec and the various available data types, along with their documented APIs or something else, I don't mind.

@safareli
Copy link
Contributor

safareli commented Dec 3, 2016

there are not so many maintainers

To be precise I meant there are not so many maintainers with much time. if the limited resource of maintainers were focused on small set of libs, we would have much better quality libs which are up to date, correct and documented, but I might be wrong.

some optionals are not Functors

I meant Optionals which trate null/undefined in special way i.e ignoring functor laws, like this:

Optional.prototype.map = function(f) {
 return this.value == null : this ? f(this.value)
}

(don't know of an lib exactly, but have seen it in couple articles)

I don't see that law defined anywhere in FL, nor do I think it's actually necessary. This would suggest that if an implementation can be derived then it must be, rather than being able to use a more optimal one, despite both choices evaluating to the same value.

From FL:

If a data type provides a method which could be derived, its behaviour must be equivalent to that of the derivation (or derivations).

Executing Tasks in parallel is not equivalent to executing Tasks in sequence, even if they evaluate to the same value, this was discussed in fantasyland/fantasy-land#179 and rpominov/fun-task#28.

@davidchambers
Copy link
Member Author

There could still be room for competing implementations if the data-type defined in FL was kept to a "minimum viable data-type" that just implemented the constructors, deconstructors of some kind and the FL spec. This would allow existing libraries to implement any various supporting libraries that they wished to while keeping the core data-type reusable across libraries.

This is exactly what I have in mind. 👍

Competition is a good thing in many cases, @CrossEye, but I believe the value of having multiple competing implementations of an ADT with the same set of methods with (presumably) identical behaviour is outweighed by the loss of interoperability.

Competition is more beneficial at the level above the basic ADT implementations. For example, it would be exciting to see Folktale and Sanctuary depend on fantasy-eithers, but for one to provide a Scala-inspired object-oriented interface while the other provides a Haskell-inspired function-based interface (with optional type checking).

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

8 participants