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

more accessible documentation? #178

Open
donhatch opened this issue May 2, 2018 · 16 comments
Open

more accessible documentation? #178

donhatch opened this issue May 2, 2018 · 16 comments

Comments

@donhatch
Copy link

donhatch commented May 2, 2018

I have trouble taking native/A+ promises seriously, mostly due to its impossible-to-analyze behavior around automagically unwrapping thenables (I believe this is commonly known as "failure to be a monad").

As I consider long-term solutions, alternatives like fantasy-land and creed::async become quite attractive.
But, frustratingly, my several attempts to dive into either one of them have failed, due to my failure to being able to follow the documentation of either, to any significant depth. I also have the feeling that, even if I succeed in vaulting the very high bar to entry, I will leave my normal friends and coworkers behind, since they will be unable to ever read my code from then on.

  • The fantasy-land doc dives straight into algebraic "abstract nonsense" (I don't neceessarily use the term dismissively, but it does make that doc impenetrable and thus not useful to me for learning).
  • fluture-js/Fluture might be a decent alternative; I'll explore that in parallel.

This creed::async certainly sounds great, from its introductory blurb (great marketing!), so I'd really like to try it, so that's what brings me here.

As I continue reading the README, I encounter:

  • The async-problem example. Ok, I guess it solves this puzzle neatly. Can't really make head nor tail of the details at this point, and it's doesn't seem that relevant to my wish to learn the library.
  • The "Try it" section. Ok, I follow this section: it looks just like the Promises I know, so far, but there's not a lot in this section.
  • ... scrolling down, hoping to see some more introductory examples of how to use various features, and I reach:
  • API : Run async tasks: coroutine :: Generator -> (...* --> Promise e a) : Create an async coroutine from a promise-yielding generator. [... example that doesn't seem relevant to me yet ...] WHOA! I suddenly feel very far out of my depth...
  • fromNode :: NodeApi e a --> (...* --> Promise e a) [... more stuff that doesn't seem relevant to me at all ...]
  • scrolling down more, I see lots more API reference and code examples, but they all seem to assume I already know what's going on. I'm lacking any context or feeling like I know how to get my foot in the door.

What I'm trying to say is... is there any chance of getting some introductory material in there,
to bridge the large gap between the shallow "Try It" section and the deep "API" section, for programmers like me who want to learn this library?

In particular, I'd be interested in some dedicated material explaining, in both plain language and code:

  • A list of each the async constructs/styles that creed::async provides, with high-level description of pros and cons of each compared to each other.
  • Compare/contrast these constructs/styles with native/A+ promises and native async/await, point out the differences / added-value that are the reason a reasonable person would want to use this library.
  • Maybe also compare/contrast with other alternative libraries like Fluture? I actually don't know how you view creed::async in relation to other alternatives at this point, and it would be good to know.
  • Then ease into more depth, with some well-motivated examples of each construct/style without assumption of prior knowledge, with explanations and code comments less terse than the API examples.
  • My impression, from reading your and others' comments in other discussion threads that lead here, is that a crucial motivating point about this library is something like "creed::async::Promise is A+ compliant since it has a compliant then, but if you want something with analyzable semantics, don't use that, use its 'chain' instead". But I don't see that stated or even alluded to anywhere in the creed::async doc! (And, truthfully, I'm not even sure I have it straight.) I feel like there may be a lot of other important context and motivation like this that I'm missing, too. A dedicated "Motivation" section might go a long way.

A final note-- personally, I know Promises/A+ already, so I don't mind if the doc assumes that knowledge, for my own use in learning the library. However, if this library is intended to be a serious option for the world for doing async, it would be great if there were also an introduction from first principles for javascript programmers, so that people can skip A+ and get right to the sane stuff. That would be a more ambitious undertaking, though.

@Frikki
Copy link

Frikki commented May 4, 2018

Let me attempt to address.

I have trouble taking native/A+ promises seriously

Okay.

mostly due to its impossible-to-analyze behavior around automagically unwrapping thenables (I believe this is commonly known as "failure to be a monad").||

Belief belongs to a concept called religion.

As I consider long-term solutions, alternatives like fantasy-land and creed::async become quite attractive.

Okay.

But, frustratingly, my several attempts to dive into either one of them have failed, due to my failure to being able to follow the documentation of either, to any significant depth.

What could be bettered?

I also have the feeling that, even if I succeed in vaulting the very high bar to entry, I will leave my normal friends and coworkers behind, since they will be unable to ever read my code from then on.

The tragedy of the commons. If your co-workers cannot understand your code, then write it so they can. If you cannot do that, the library doesn’t apply to the level of your co-workers. Not everybody understands Haskell either.

The fantasy-land doc dives straight into algebraic "abstract nonsense" (I don't neceessarily use the term dismissively, but it does make that doc impenetrable and thus not useful to me for learning).

Abstract nonsense? Since when was abstract nonsense? Is category theory, for example, nonsense? After all, it’s abstract as f**k.

fluture-js/Fluture might be a decent alternative; I'll explore that in parallel.

I agree. You should. It’s good to be an explorer. 42 is not the answer. O, well ...

This creed::async certainly sounds great, from its introductory blurb (great marketing!), so I'd really like to try it, so that's what brings me here.

I had the same feeling about JavaScript.

he async-problem example. Ok, I guess it solves this puzzle neatly. Can't really make head nor tail of the details at this point, and it's doesn't seem that relevant to my wish to learn the library.

Okay. What would be relevant?

The "Try it" section. Ok, I follow this section: it looks just like the Promises I know, so far, but there's not a lot in this section.

Fair enough. What should be added?

... scrolling down, hoping to see some more introductory examples of how to use various features, and I reach:
API : Run async tasks: coroutine :: Generator -> (...* --> Promise e a) : Create an async coroutine from a promise-yielding generator. [... example that doesn't seem relevant to me yet ...] WHOA! I suddenly feel very far out of my depth...

Keep swimming. Maybe a submarine is a good example? Better yet, what are you looking for?

fromNode :: NodeApi e a --> (...* --> Promise e a) [... more stuff that doesn't seem relevant to me at all ...]

I once went to a dating site, and ... well, same.

scrolling down more, I see lots more API reference and code examples, but they all seem to assume I already know what's going on. I'm lacking any context or feeling like I know how to get my foot in the door.

You’re looking for basics?

What I'm trying to say is... is there any chance of getting some introductory material in there,
to bridge the large gap between the shallow "Try It" section and the deep "API" section, for programmers like me who want to learn this library?

I belive that could be improved. Likely an article addressing your particular use case.

I have to stop here because I am getting tired reading the flood of text that is mostly a complaint about communication not fitting a particular purpose. I’d love to address your concerns later ... maybe after your next post.

@Avaq
Copy link

Avaq commented May 4, 2018

the flood of text that is mostly a complaint about communication not fitting a particular purpose

I don't think @donhatch is complaining, I think they are raising valid concerns about the accessibility of the alternative Promise libraries. You might be too hard on them in your response, @Frikki. I think most of what @donhatch said stems from confusion.

I have trouble taking native/A+ promises seriously, mostly due to its impossible-to-analyze behavior around automagically unwrapping thenables (I believe this is commonly known as "failure to be a monad").

This is exactly the kind of complaint that we would expect from the target audience of alternative Promise libraries. Using Creed, Fluture, Folktale, or similar is indeed a way to avoid having to deal with the absurdity of the native Promise implementation.

As I consider long-term solutions, alternatives like fantasy-land and creed::async become quite attractive.

This seems to highlight the first points of confusion: that Fantasy Land is an alternative to native Promise/A+ somehow.

You don't need to look at Fantasy Land if you want an alternative to Promises/A+. Fantasy Land only exists to acknowledge within the JS community that some constructs can be related to category theory, and made to interoperate because of that. Fantasy Land describes the association with category theory (hence the abstract nonsense) and an interface for independent libraries to be able to use each others algebraic operations.

As I continue reading the README, I encounter [a lot of in-depth material]
What I'm trying to say is... is there any chance of getting some introductory material in there,
to bridge the large gap between the shallow "Try It" section and the deep "API" section, for programmers like me who want to learn this library?

The problem you're running into is that a lot of these documentations assume understanding of underlying concepts. These concepts are broad, and too much for every individual library to cover, but they can also be very widely applied. A great place to start is the Mostly Adequate Guide. Many of the concepts covered there can be extrapolated to understand the documentations of functionally minded libraries.

My impression [...] is that a crucial motivating point about this library is something like [...] "it has a [Promises/A+] compliant then, but if you want something with analyzable semantics, don't use that, use its chain instead"

That's right. Promises/A+ is another spec drafted with interoperability in mind, and for the benefit of interoperability, the people who drafted the spec arbitrarily decided upon these strange assimilation semantics you've mentioned before. In order for Promises to interoperate, the then function must behave strangely. The Native Promise implementation (and Bluebird, and most others) took it one step further though, and added the same behaviour to all Promise functions (including all of its constructors), making it so there is no escape from the strange semantics. Creed is different in that it has the minimum necessary to be spec compliant, but it also has sane alternatives to the then function. You as a user are encouraged to use the sane alternatives (like map and chain) and leave then as a means for interoperability and colleagues not willing to make the leap. As an added benefit, map and chain and friends are compliant with the Fantasy Land spec, meaning that interoperability with libraries such as Ramda is also supported.

A dedicated "Motivation" section might go a long way.

I think that's a good suggestion.

if this library is intended to be a serious option for the world for doing async, it would be great if there were also an introduction from first principles for javascript programmers

I see where you are coming from, but as I mentioned, the underlying principles are shared between all functionally minded libraries and are a lot to cover. Once you are familiar with the basics I assure you all of these documentations will make a lot more sense! In the Fluture documentation, I try to link to material on the basics whenever necessary. It's my best idea for guiding new users. Perhaps Creed can do the same. How do you think it can be improved?

@donhatch
Copy link
Author

donhatch commented May 4, 2018

@Frikki Although there are apparently several questions in your reply, I don't see anything that looks like it really wants an answer. All of your "what could be better?" "what would be relevant?" "you're looking for basics?" questions are things I did attempt to address in my original post and even in the parts of it that you quoted, and I don't have the sense that I would make anything better by repeating those parts.

I hear that you perceive much of my post as complaining and as a wall of text half of which you didn't read. Okay.

Regarding whether category theory is "abstract nonsense"... yes. Again, I don't use the term to be dismissive or derogatory; I mean it in the sense well-described in the Background section of the linked wikipedia article, which agrees with how my category theory professor used the term.

@donhatch
Copy link
Author

donhatch commented May 4, 2018

@Avaq Thank you! Your reply was incredibly helpful to me, as it clarifies quite a lot of what I was wondering about and was unsure of about creed::async. In fact, as I look it over again, I get the sense that the entire text of your reply, if it were simply dropped into an early part of the README with minor edits, would serve fantastically as exactly the motivational and contextual bridge that I was missing.

Yes, I find the Fluture documentation to be quite accessible; things like your links to basics contribute well to that, as do your many comments and cross-links from one concept to related concepts within the doc itself. My sense is that if the creed::async API doc could be filled out a bit with such comments and cross-links, it would become similarly accessible.

For one very specific example: in the API section, I'd get benefit from seeing "then" and "chain" cross-reference each other with something like "chain is then without the automatic unwrapping". And many similar things like that.

@donhatch
Copy link
Author

donhatch commented May 4, 2018

@Avaq Just to clarify this particular point...

if this library is intended to be a serious option for the world for doing async, it would be great if there were also an introduction from first principles for javascript programmers

I see where you are coming from, but as I mentioned, the underlying principles are shared between all functionally minded libraries and are a lot to cover. Once you are familiar with the basics I assure you all of these documentations will make a lot more sense! In the Fluture documentation, I try to link to material on the basics whenever necessary. It's my best idea for guiding new users. Perhaps Creed can do the same. How do you think it can be improved?

Sure, I'm not suggesting writing another introduction to common introductory material that exists elsewhere-- I agree that links to such (with an appropriate amount of explanation of why they are being linked and how they relate to the current material), serve quite well for that.

When I said "from first principles" (probably a poor choice of words), I meant specifically "without depending on Promises/A+ documentation". Promises/A+ serves a necessary purpose at the moment, but, in an ideal future, Promises/A+ will be forgotten and more tenable projects like this one will live on, so it would be good to avoid dependencies on Promises/A+ docs (other than perhaps for historical context-- not for concepts).

@dmitriz
Copy link
Contributor

dmitriz commented May 5, 2018

@donhatch

I have trouble taking native/A+ promises seriously, mostly due to its impossible-to-analyze behavior around automagically unwrapping thenables (I believe this is commonly known as "failure to be a monad").

In fact, Promise is not even a Functor.
And sure enough, you better not use any then prop anywhere inside your objects ;)

As I consider long-term solutions, alternatives like fantasy-land and creed::async become quite attractive.

Fantasy-land is not an alternative, it is not even a library. It is more of a collection of densely written and opinionated specs aimed at library writers. It does assume familiarity with many concepts it mentions and does not aim to provide any introduction nor give examples.
Static Land is perhaps more user-friendly, it is still a spec though.

For something more accessible, in addition to the excellent "Professor Frisby's Mostly Adequate Guide to Functional Programming" mentioned by @Avaq, have a look at the practical examples in https://github.com/dmitriz/functional-examples.

Creed is entirely different, it is an actual library.

The async-problem example. Ok, I guess it solves this puzzle neatly. Can't really make head nor tail of the details at this point, and it's doesn't seem that relevant to my wish to learn the library.

It is true that adding some more explanations to this example would not hurt.
@briancavalier is very friendly and open to suggestions, so feel free to make some.

The "Try it" section. Ok, I follow this section: it looks just like the Promises I know, so far, but there's not a lot in this section.

It does show some good features to get started, as well as the friendly REPL inspector facility.
The use of map there is actually quite interesting:

> all([1, 2, 3].map(resolve))
Promise { fulfilled: 1,2,3 }

and perhaps not "too introductory" as it simultaneously uses 2 new operators.
To get some better feeling, it always helps to play with those in isolation:

> creedPromise = resolve('hello')
Promise { fulfilled: hello }
> creedPromise1 = creedPromise.map(str => str + '?')
Promise { pending }
> creedPromise1
Promise { fulfilled: hello? }
> wrappedPromise = creedPromise.map(resolve)
Promise { pending }
> wrappedPromise
Promise { fulfilled: [object Promise { fulfilled: hello }] }
> together = all([creedPromise, creedPromise1])
Promise { fulfilled: hello,hello? }
// WAT? Ok, that one was a bit cryptic, so let's test it ...
> together.map(console.log)
Promise { pending }
> [ 'hello', 'hello?' ]

So we see that map is more atomic than then in that it does not run any unwrapping "magic". And all seems to run an array of promises in parallel, similar to Promise.all:

> native = Promise.all([creedPromise, creedPromise1])
Promise {
   ...  (mostly useless information from the native promise inspector)
> native.map(console.log)
TypeError: native.map is not a function
> native.then(console.log)
   ... 
> [ 'hello', 'hello?' ]

... scrolling down, hoping to see some more introductory examples of how to use various features, and I reach:
API : Run async tasks: coroutine :: Generator -> (...* --> Promise e a) : Create an async coroutine from a promise-yielding generator. [... example that doesn't seem relevant to me yet ...] WHOA! I suddenly feel very far out of my depth...

Indeed, this surely is an advanced one, outside the core methods, not clear why it comes first...

fromNode :: NodeApi e a --> (...* --> Promise e a) [... more stuff that doesn't seem relevant to me at all ...]

That one is actually more basic, demonstrating how to turn a method from NodeApi into a creed promise:

> let {fromNode} = require('creed')
undefined
> readFileToCreedPromise = fromNode(fs.readFile)
[Function: promisified]
> readFileToCreedPromise('someFile', 'utf8')
Promise { pending }
> Error: ENOENT: no such file or directory, open 'someFile'

What I'm trying to say is... is there any chance of getting some introductory material in there,
to bridge the large gap between the shallow "Try It" section and the deep "API" section, for programmers like me who want to learn this library?

It is true that an "Introduction" section aimed at "ordinary promise users" is missing.

In particular, I'd be interested in some dedicated material explaining, in both plain language and code: ...

These are excellent suggestions. An introductory section "Why would I use creed?" for regular promise users would certainly lower the access bar. Maybe start with some scary "then-able" surprises and move on showing how things are more transparent and easier to reason about with the sane map and chain methods resting on years of research in computer science and mathematics.

@unscriptable
Copy link
Contributor

Maybe start with some scary "then-able" surprises and move on showing how things are more transparent and easier to reason about with the sane map and chain methods resting on years of research in computer science and mathematics.

This. 💯

@bergus
Copy link
Contributor

bergus commented May 5, 2018

Maybe start with some scary "then-able" surprises and move on to …

I would not recommend to start a tutorial with that. New users want to learn how to use the Creed library, not hear our opinions about why then is horrible. Sure, it should be mentioned somewhere, but not at the beginning.

@briancavalier
Copy link
Owner

Hi everyone. Thanks for the discussion. I'm sorry I've not been able to respond until the weekend (my time lately is very limited during the week)

I think there are some very good suggestions in here, and I'd like to try to focus subsequent discussion around those. Hopefully we can get to some tangible goals and start to turn them into concrete doc improvements.

Here are the things I saw mentioned that seem like they would be helpful improvements:

  1. Add simple "Introduction" and/or "Why would I use creed" sections
  2. Add another 1-2 simple examples to the README.
  3. Add links to helpful information about foundational functional programming concepts, such as the Mostly Adequate Guide.
  4. Perhaps more clearly encourage exploration via REPL.

I like all of these ideas, and I'm open to doing them.

If creed moves forward with these, I'd love help. As I mentioned, my time has been very limited over the past few weeks, and that's likely to continue for at least another 1-2 weeks. Discussion is helpful, and of course PRs would also be helpful.

@dmitriz
Copy link
Contributor

dmitriz commented May 6, 2018

@bergus

Maybe start with some scary "then-able" surprises and move on to …

I would not recommend to start a tutorial with that. New users want to learn how to use the Creed library, not hear our opinions about why then is horrible. Sure, it should be mentioned somewhere, but not at the beginning.

I actually would find it helpful.

My first questions, when seeing a new library, are not "How to use it?" but "Why use it?", "What it brings to the table?" and "What it does that X and Y don't do?

In this particular case, we have a library seemingly similar to the native Promise yet with at least twice as many methods that can be easily overwhelming for a newcomer. It clearly serves a wide range of people's expertise levels and relies on years of experience, but that also makes it harder for newcomers to answer those questions.

Concerning .then, it is actually wonderful in that it manages to do so much under the single method namespace. 😄 However, that ease and simplicity come at price of risks entailed in the whole design as e.g. is beautifully described in the Medium post
https://medium.com/@avaq/broken-promises-2ae92780f33 by @Avaq.
The problem is, such posts are rare, whereas the "glowing praise" posts are numerous that often skip the hard truth. But people who rely on this design for their work, deserve to know all sides, not only the shiny ones.

Without knowing that other side of equation, native promises look wonderfully easy to use and "working just fine" and "being used by everyone without problems", so why making life harder by "pleasing some few category theory sadists" 😄 I have not made it up, that is really what I've seen written even by experienced programmers. To which I can't think of any better response than by @tjaskula in his highly educational Medium article Can programming be liberated from the von Neumann style?:

In the end the popularity might be an evidence of minimum level of quality acceptable by the majority of people.

I understand it has some deeper roots in certain unfortunate education culture, that we obviously can't fix here. What we can do though, is explain how and where that knowledge can be practically beneficial in the specific use cases that Creed is addressing.

As for well-motivated opinions by people with experience, these are actually quite helpful to newcomers and great way to learn quickly and save a lot of time. As any other library, this one is based on certain opinions of the people who designed it, and knowing and understanding those is actually incredibly helpful, specifically when using the library.

@briancavalier
Copy link
Owner

In addition to these:

  • it seems helpful for the API docs to emphasize map, et al. and group A+ / ES interop functions (i.e. then, catch, and finally) together and explain more clearly that's their purpose.

@dmitriz
Copy link
Contributor

dmitriz commented May 9, 2018

@briancavalier

it seems helpful for the API docs to emphasize map, et al. and group A+ / ES interop functions (i.e. then, catch, and finally) together and explain more clearly that's their purpose.

In this direction, it would be good to have some very basic but realistic examples.
(My definition of "basic" is strictly one method from the library,
with strict focus on that method with any possible distraction/complication removed.)

I will look into rewriting the Task-based examples into creed-based in
https://github.com/dmitriz/functional-examples
and perhaps adding some more.
With the idea that the best ones can be later imported here.

Any PR to
https://github.com/dmitriz/functional-examples
or
https://github.com/dmitriz/monadic-libraries-examples
is of course welcome ;)

@briancavalier
Copy link
Owner

@dmitriz Thank you for putting together those examples!

I think the next step for this particular issue is actually to create a new issue that represents the concrete work to be done--from here and here, and potentially drawing from (and/or linking to) @dmitriz's examples.

Once again, thank you, everyone for the discussion and suggestions.

@briancavalier
Copy link
Owner

See #179

@briancavalier
Copy link
Owner

It turns out I was swamped for more than the 1-2 weeks I originally thought, but I just started working on the items in #179.

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

7 participants