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

Add docs for Arrow #1924

Merged
merged 5 commits into from
Sep 29, 2017
Merged

Add docs for Arrow #1924

merged 5 commits into from
Sep 29, 2017

Conversation

zliu41
Copy link
Contributor

@zliu41 zliu41 commented Sep 20, 2017

issue: #1801

Initial draft for Arrow documentation. Did this as part of the Scala World open source spree.

@codecov-io
Copy link

codecov-io commented Sep 21, 2017

Codecov Report

Merging #1924 into master will increase coverage by 0.02%.
The diff coverage is n/a.

Impacted file tree graph

@@            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
Impacted Files Coverage Δ
core/src/main/scala/cats/Eval.scala 98.75% <0%> (-1.25%) ⬇️
core/src/main/scala/cats/syntax/alternative.scala 100% <0%> (ø) ⬆️
core/src/main/scala/cats/syntax/either.scala 99.13% <0%> (ø) ⬆️
core/src/main/scala/cats/data/EitherT.scala 98.36% <0%> (+0.08%) ⬆️
core/src/main/scala/cats/Alternative.scala 88.88% <0%> (+1.38%) ⬆️
core/src/main/scala/cats/arrow/Arrow.scala 100% <0%> (+20%) ⬆️

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 664cb62...cb87f8e. Read the comment docs.

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

@LukaJCB LukaJCB Sep 21, 2017

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" :)

Copy link
Contributor Author

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

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

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?

Copy link
Contributor Author

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

Choose a reason for hiding this comment

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

Same as above

Copy link
Member

@LukaJCB LukaJCB left a 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 :)

@LukaJCB LukaJCB mentioned this pull request Sep 21, 2017
70 tasks

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

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?

Copy link
Contributor Author

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.

Copy link
Contributor

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

Copy link
Contributor Author

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

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

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.

@zliu41
Copy link
Contributor Author

zliu41 commented Sep 24, 2017

Updated. Added examples for Function1 and Kleisli in addition to the original examples :)

Copy link
Contributor

@kailuowang kailuowang left a 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)
Copy link
Contributor

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?

Copy link
Contributor Author

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

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

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?

Copy link
Contributor Author

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.

@zliu41
Copy link
Contributor Author

zliu41 commented Sep 29, 2017

Rewritten the first paragraph based on @kailuowang's suggestion.

@LukaJCB LukaJCB merged commit a68c80b into typelevel:master Sep 29, 2017
@zliu41
Copy link
Contributor Author

zliu41 commented Sep 30, 2017

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.

@kailuowang kailuowang added this to the 1.0.0-RC1 milestone Oct 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants