-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
Add docs for Arrow #1924
Add docs for Arrow #1924
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1924 +/- ##
==========================================
+ Coverage 95.55% 95.57% +0.02%
==========================================
Files 248 248
Lines 4430 4454 +24
Branches 117 121 +4
==========================================
+ Hits 4233 4257 +24
Misses 197 197
Continue to review full report at Codecov.
|
--- | ||
# Arrow | ||
|
||
`Arrow` is a useful type class for modeling something that behaves like functions, such as `Function1`: `A => B`, `Kleisli`: `A => F[B]` (also known as `ReaderT`), `Cokleisli`: `F[A] => B`, etc. So useful, that Haskell provides special syntax (the `proc` notation) for composing and combining Arrows, similar as the `do` notation for sequencing monadic operations. |
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 "similar to" would be better than "similar as" :)
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. I can be pretty bad at choosing the right preposition :)
``` | ||
|
||
Once a type `F` has an `Arrow` instance, it gets for free a number of methods for composing and combining with other `Arrow`s. You will be able to do things like: | ||
- Composing `fab: F[A, B]` and `fbc: F[B, C]` into `fac: F[A, C]` with `fab >>> fbc`. If `F` is `Function1` then `>>>` becomes alias of `andThen`. |
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 it should be "becomes an alias for" :)
|
||
```tut:book:silent | ||
runList(accum[Int, Int](0)(_ + _), List(6, 5, 4, 3, 2, 1)) | ||
// res1: List[Int] = List(6, 11, 15, 18, 20, 21) |
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.
Can we not make this non-silent? Then we could remove the comment, or am I missing something?
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.
You are right, I'm not super familiar with tut.
|
||
```tut:book:silent | ||
runList(avg, List(1, 10, 100, 1000)) | ||
// res2: List[Int] = List(1.0, 5.5, 37.0, 277.75) |
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 above
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.
Couple of minor things, should be resolved very quickly. Otherwise looks really great to me! Awesome work :)
|
||
That is, given an `A`, it not only returns a `B`, but also returns a new `FancyFunction[A, B]`. This sounds similar as the `State` monad (which returns a result and a new `State` from an initial `State`), and indeed, `FancyFunction` can be used to perform stateful transformations. | ||
|
||
Here's an `Arrow` instance for `FancyFunction`: |
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.
Would you mind giving an example of use of FancyFunction
before showing the Arrow
instance implementation?
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.
Yep. There's now an example of how to use avg
, before showing the Arrow instance for FancyFunction
and explaining how to implement avg
.
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.
Thanks @zliu41! I left a few comments based on feedback that we've gotten on Cats documentation in the past. It seems that for a lot of people seeing some examples of how something is used before diving into the details of how it works tends to help them frame/understand it. I think that with just a bit of tweaking this will be good to go!
--- | ||
# Arrow | ||
|
||
`Arrow` is a useful type class for modeling something that behaves like functions, such as `Function1`: `A => B`, `Kleisli`: `A => F[B]` (also known as `ReaderT`), `Cokleisli`: `F[A] => B`, etc. So useful, that Haskell provides special syntax (the `proc` notation) for composing and combining arrows, similar to the `do` notation for sequencing monadic operations. |
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 that we should avoid bringing Haskell into the explanation this early in the docs (if at all). I know that for people who are interested in functional programming, Haskell is the go-to language to describe concepts, but in my general experience people who already know haskell will already be familiar with concepts such as arrows, and mentioning Haskell won't be helpful for people who don't already know it.
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.
Good point.
|
||
`Arrow` is a useful type class for modeling something that behaves like functions, such as `Function1`: `A => B`, `Kleisli`: `A => F[B]` (also known as `ReaderT`), `Cokleisli`: `F[A] => B`, etc. So useful, that Haskell provides special syntax (the `proc` notation) for composing and combining arrows, similar to the `do` notation for sequencing monadic operations. | ||
|
||
To create an `Arrow` instance for a type `F[A, B]`, the following abstract methods need to be implemented: |
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 might be helpful to show a few examples of using Arrow
methods on instances that already exist (such as Function1
before diving into what's needed to create your own custom Arrow
instance. It's very rare that you'll be creating your own custom Arrow
instance, but more common that people will want to take advantage of some of the methods on existing types.
|
||
Once a type `F` has an `Arrow` instance, it gets for free a number of methods for composing and combining multiple `Arrow`s. You will be able to do things like: | ||
- Composing `fab: F[A, B]` and `fbc: F[B, C]` into `fac: F[A, C]` with `fab >>> fbc`. If `F` is `Function1` then `>>>` becomes an alias for `andThen`. | ||
- Taking two arrows `fab: F[A, B]` and `fbc: F[B, C]` and combining them into `F[(A, C) => (B, D)]` with `fab *** fbc`. The resulting arrow takes two inputs and processes them with two arrows, one for each input. |
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 related to the previous comment, but I think that some concrete examples might help these explanations.
Updated. Added examples for |
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.
Thanks for this wonderful document! Very helpful examples. I left a nit comment above.
|
||
```tut:book:silent | ||
runList(accum[Int, Int](0)(_ + _), List(6, 5, 4, 3, 2, 1)) | ||
// res1: List[Int] = List(6, 11, 15, 18, 20, 21) |
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.
Curious why use tut:silent and manually write the output? Tut's output won't work?
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 was fixed in the 2nd commit. First time using tut..
|
||
```tut:book:silent | ||
runList(avg, List(1, 10, 100, 1000)) | ||
// res2: List[Int] = List(1.0, 5.5, 37.0, 277.75) |
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 above. Why not just tut:book?
--- | ||
# Arrow | ||
|
||
`Arrow` is a type class for modeling something that behaves like functions. For example, `scala.Function1`(`A => B`), `cats.data.Kleisli`(wrapping an `A => F[B]`, also known as `ReaderT`), and `cats.data.Cokleisli`(wrapping an `F[A] => B`), have `Arrow` instances. |
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.
Sorry I am late in the game. This is kind of a nit but I am not so sure about this very first sentence.
Arrow
is a type class for modeling something that behaves like functions.
I kind of feel that this is not the original intention of the type class. Arrow
is, well, arrow in category theory. function is just one of the possible definitions. So a more precise way to put it might be
`Arrow` is a type class for modeling composable relationship between two types. One example of such composable relationship is function `A => B`, other examples includes `cats.data.Kleisli`(wrapping an `A => F[B]`, also known as `ReaderT`), and `cats.data.Cokleisli`(wrapping an `F[A] => B`), have `Arrow` instances.
WDYT?
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.
sgtm. Thanks for the correction.
Rewritten the first paragraph based on @kailuowang's suggestion. |
Would like to thank @LukaJCB, @julienrf, @ceedubs and @kailuowang for the feedback, and @peterneyens for helping me get started at Scala World. Looking forward to making more contributions to Cats in the future. |
issue: #1801
Initial draft for
Arrow
documentation. Did this as part of the Scala World open source spree.