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

Improve docs to better explain monads #956

Merged
merged 34 commits into from Aug 1, 2018
Merged

Improve docs to better explain monads #956

merged 34 commits into from Aug 1, 2018

Conversation

pakoito
Copy link
Member

@pakoito pakoito commented Jul 28, 2018

BIG DUMP!

  • Add Monad docs
  • Add a separate monad tutorial based off the C# one (patterns/monads)
  • Improve intro to typeclasses
  • Improve wording in comprehensions

@codecov
Copy link

codecov bot commented Jul 28, 2018

Codecov Report

Merging #956 into master will decrease coverage by 0.01%.
The diff coverage is n/a.

Impacted file tree graph

@@             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
Impacted Files Coverage Δ Complexity Δ
...ics/src/main/kotlin/arrow/optics/instances/mapk.kt 86.36% <0%> (-4.55%) 0% <0%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update e6c2396...25b84f0. Read the comment docs.

Copy link
Member

@JorgeCastilloPrz JorgeCastilloPrz left a 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.

@pakoito
Copy link
Member Author

pakoito commented Jul 28, 2018

@JorgeCastilloPrz done, I've added a whole new section and renamed the folder. Feel free to re-review.

@pakoito
Copy link
Member Author

pakoito commented Jul 28, 2018

@JorgeCastilloPrz done, try again :D

Copy link
Member

@JorgeCastilloPrz JorgeCastilloPrz left a 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.

Copy link
Contributor

@Takhion Takhion left a 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.
Copy link
Contributor

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.
Copy link
Contributor

@Takhion Takhion Jul 29, 2018

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 { ... }
Copy link
Contributor

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()
Copy link
Contributor

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing .nextTalk().execute()?

Copy link
Member Author

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:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

- AddStep
+ `addStep`

Copy link
Contributor

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.
Copy link
Contributor

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:
Copy link
Contributor

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>
Copy link
Contributor

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.
Copy link
Contributor

@Takhion Takhion Jul 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[same as this]

@pakoito
Copy link
Member Author

pakoito commented Jul 29, 2018

The lack of `` was intentional, I may do a pass and add it now.

@pakoito
Copy link
Member Author

pakoito commented Jul 31, 2018

@Takhion I've addressed most. I've kept `` only on those types with generics.


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.

Copy link

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.

Copy link

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.
Copy link

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.

Copy link
Member Author

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
Copy link

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.

Copy link
Member Author

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.
Copy link

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"

Copy link
Member Author

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
Copy link

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....

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added one

@pakoito pakoito merged commit 73b9a97 into master Aug 1, 2018
@pakoito pakoito deleted the paco-docsafterhadi branch August 1, 2018 22:38
@pakoito pakoito mentioned this pull request Aug 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants