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
Improve docs to better explain monads #956
Conversation
Codecov Report
@@ Coverage Diff @@
## master #956 +/- ##
============================================
- Coverage 46.72% 46.71% -0.02%
Complexity 649 649
============================================
Files 308 308
Lines 8011 8011
Branches 821 821
============================================
- Hits 3743 3742 -1
Misses 3938 3938
- Partials 330 331 +1
Continue to review full report at Codecov.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These new docs for Monad look very well and gradual. You showcase the pattern they try to solve with a bunch of different data types, and then move into unveiling that pattern as the Monad. Then you keep going and show comprehensions and other more advanced stuff. Good job there.
Still I find something missing. I've heard many people (and not a single time) thinking that Monads are the data types themselves. As in Option, Try, Either and so on being Monads. There's some confusion with that and I think it's quite extended. In some way they "are" since you can flatMap over those, but mostly because they provide an instance for Monad.
It might be good to clarify that as soon as Monad becomes completely explained on this tutorial. Also maybe a link to Typeclasses docs in the end after saying Monad is one of the Typeclasses provided. Typeclasses would probably require docs on the same style than this one, which is probably the best approach possible.
I'd also probably rename the section to be plainly ...patterns/monad. I don't see a need for euphemisms on the URL. People DO know the Monad word, but actually not what does it mean. So they'll need to find it by its name and then find the explanation they're looking for inside.
@JorgeCastilloPrz done, I've added a whole new section and renamed the folder. Feel free to re-review. |
@JorgeCastilloPrz done, try again :D |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. I'd really like to have Hadi reviewing this though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Love it!!
I just highlighted some minor code/grammar fixes/suggestions.
Ah I might have left, uhm, a few of them 😅
@@ -12,7 +12,10 @@ NOTE: The docs are currently at around 60% completion. They're the present prior | |||
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0) | |||
|
|||
Λrrow is a library for Typed Functional Programming in Kotlin. | |||
It includes the most popular data types, type classes and abstractions such as `Option`, `Try`, `Either`, `IO`, `Functor`, `Applicative`, `Monad` to empower users to define pure FP apps and libraries built atop higher order abstractions. | |||
|
|||
Arrow aims to provide a *lingua franca* of interfaces and abstractions across Kotlin libraries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might want to add the following and/or a link to Wikipedia:
lingua franca (i.e. a common/universal language)
README.md
Outdated
@@ -7,7 +7,11 @@ | |||
[![codecov](https://codecov.io/gh/arrow-kt/arrow/branch/master/graph/badge.svg)](https://codecov.io/gh/arrow-kt/arrow) | |||
|
|||
Λrrow is a library for Typed Functional Programming in Kotlin. | |||
It includes the most popular data types, type classes and abstractions such as `Option`, `Try`, `Either`, `IO`, `Functor`, `Applicative`, `Monad` and many more empowering users to define pure FP apps and libraries built atop higher order abstractions. Use the below list to learn more about Λrrow's main features. | |||
|
|||
Arrow aims to provide a *lingua franca* of interfaces and abstractions across Kotlin libraries. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[same as this]
|
||
```kotlin | ||
object Mapper { | ||
fun func(a: ClassA): ClassB { ... } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think using an object
might be confusing for some, perhaps this would be simpler?
- I can use static method:
-
- object Mapper {
- fun func(a: ClassA): ClassB { ... }
- }
+ I can use a top-level/static method:
+
+ fun func(a: ClassA): ClassB { ... }
return | ||
speaker | ||
.then(talk -> talk.getConference()).execute() | ||
.then(conf -> conf.getCity()).execute() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incorrect lambda syntax
- .then(talk -> talk.getConference()).execute()
- .then(conf -> conf.getCity()).execute()
+ .then { talk -> talk.getConference() }.execute()
+ .then { conf -> conf.getCity() }.execute()
```kotlin | ||
fun nextTalkCity(speaker: Speaker): Task<City> { | ||
return | ||
speaker |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing .nextTalk().execute()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ye
} | ||
``` | ||
|
||
Subsequently, AddStep is called two times to transfer to Conference and then City inside the same container: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- AddStep
+ `addStep`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Conference and then City
+ `Conference` and then `City`
|
||
Constructor is used to put an object into container `Kind<F, A>` as described in the [glossary]({{ '/docs/patterns/glossary/#type-constructors' | relative_url }}), flatMap is used to replace one contained object with another contained object. | ||
|
||
It's important that flatMaps's argument returns Kind<F, B> and not just B, as this new contained object can have different behavior, like a left branch of Either or an async execution of IO. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- It's important that flatMaps's argument returns Kind<F, B> and not just B, as this new contained object can have different behavior, like a left branch of Either or an async execution of IO.
+ It's important that the argument of `flatMap` returns `Kind<F, B>` and not just `B`, as this new contained object can have different behavior, like a left branch of `Either` or an async execution of `IO`.
|
||
It's important that flatMaps's argument returns Kind<F, B> and not just B, as this new contained object can have different behavior, like a left branch of Either or an async execution of IO. | ||
|
||
We can think of flatMap as a combination of map and flatten as defined per following signature: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- We can think of flatMap as a combination of map and flatten as defined per following signature:
+ We can think of `flatMap` as a combination of `map` and `flatten`, as defined by following signature:
```kotlin | ||
fun <F, A> Kind<F, A>.map(f: (A) -> B) // Inherited from Functor | ||
|
||
fun <F, A> Kind<F, Kind<F, A>>.flatten(): Kind<F, A> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing return type and generic type parameter
- fun <F, A> Kind<F, A>.map(f: (A) -> B) // Inherited from Functor
+ fun <F, A, B> Kind<F, A>.map(f: (A) -> B): Kind<F, B> // Inherited from Functor
} | ||
``` | ||
|
||
You can see that, once again, it's our nice readable workflow on the left + some mechanical repeatable junction code on the right. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[same as this]
The lack of `` was intentional, I may do a pass and add it now. |
@Takhion I've addressed most. I've kept `` only on those types with generics. |
# Conflicts: # infographic/arrow-infographic.txt
|
||
Arrow aims to provide a *lingua franca* of interfaces and abstractions across Kotlin libraries. | ||
For this, it includes the most popular data types, type classes and abstractions such as `Option`, `Try`, `Either`, `IO`, `Functor`, `Applicative`, `Monad` to empower users to define pure FP apps and libraries built atop higher order abstractions. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wouldn't use the term 'define'. I'd replace it with create and write
'to empower users to create pure FP applications and libraries built using higher order abstractions
@@ -28,7 +28,7 @@ You can read more about all the [datatypes]({{ '/docs/datatypes/intro' | relativ | |||
|
|||
### Typeclasses | |||
|
|||
Typeclasses define a set of functions associated to one type. | |||
Typeclasses define a set of extension functions associated to one type. | |||
This behavior is checked by a test suite called the "laws" for that typeclass. | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
believe this is an implementation detail or how it would be defined in Kotlin, as it's using the term extension function. I think it would be better to first introduce what the concept of typeclasses are.
@@ -28,7 +28,7 @@ You can read more about all the [datatypes]({{ '/docs/datatypes/intro' | relativ | |||
|
|||
### Typeclasses | |||
|
|||
Typeclasses define a set of functions associated to one type. | |||
Typeclasses define a set of extension functions associated to one type. | |||
This behavior is checked by a test suite called the "laws" for that typeclass. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is also talking about implementation detail (test suite) and then talking about laws, without introducing the laws. Maybe it just makes sense to put the paragraph of learning more about typeclasses at the start.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rewritten!
@@ -28,7 +28,7 @@ You can read more about all the [datatypes]({{ '/docs/datatypes/intro' | relativ | |||
|
|||
### Typeclasses | |||
|
|||
Typeclasses define a set of functions associated to one type. | |||
Typeclasses define a set of extension functions associated to one type. | |||
This behavior is checked by a test suite called the "laws" for that typeclass. | |||
|
|||
You can use typeclasses as a DSL to add new free functionality to an existing type |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd explain what you mean by the use of "free" functionality.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added!
@@ -9,7 +9,7 @@ permalink: /docs/patterns/monad_comprehensions/ | |||
{:.intermediate} | |||
intermediate | |||
|
|||
Monad comprehension is the name for a programming idiom available in multiple languages. | |||
Monad comprehension is the name for a programming idiom available in multiple languages like JavaScript, F#, Scala, or Haskell. | |||
The purpose of monad comprehensions is to compose sequential chains of actions in a style that feels natural for programmers of all backgrounds. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
either "a monad comprehension is" or "monad comprehensions are"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed!
@@ -37,12 +37,15 @@ They allow us to write sequenced code that can be run asynchronously over multip | |||
|
|||
### Asynchronous sequences of actions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't see a lead in here from Monad Comprehensions....
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added one
BIG DUMP!