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 EitherT docs #1854

Merged
merged 10 commits into from
Sep 12, 2017
Merged

Add EitherT docs #1854

merged 10 commits into from
Sep 12, 2017

Conversation

Technius
Copy link
Contributor

I've been using EitherT recently, so I thought it would be a good idea to add some docs for it.

Copy link
Contributor

@iravid iravid left a comment

Choose a reason for hiding this comment

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

Nice work :-) Looks very helpful.

val error: EitherT[Option, String, Int] = EitherT.leftT("Not a number")
```

## From `F[A]` or `F[B]` to `EitherT[F, A B]`
Copy link
Contributor

Choose a reason for hiding this comment

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

Missing a comma in EitherT[F, A*,* B]

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 comments, otherwise LGTM! :)

}
```

Clearly, the updated code is less readible and more verbose: the details of the
Copy link
Member

Choose a reason for hiding this comment

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

"readable"

```

Note that since `EitherT` is a monad, monadic combinators such as `flatMap` can
be used to compose `EitherT` values.
Copy link
Member

Choose a reason for hiding this comment

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

Maybe clarify here, that EitherT forms a Monad, only if F[_] is also a Monad :)

@LukaJCB
Copy link
Member

LukaJCB commented Aug 25, 2017

Also your Tut examples seem to fail on 2.11.x and 2.10.x. You can execute + tut in the sbt console to test on all Scala versions :)

Use the `value` method defined on `EitherT` to retrieve the underlying `F[Either[A, B]]`:

```tut:book
val errorT: EitherT[Option, String, Int] = EitherT.leftT("foo")
Copy link
Member

Choose a reason for hiding this comment

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

I know it's just an example, but an EitherT[Option, String, Int] doesn't really seem that useful, and I'm not sure if we should include those in the official docs. Maybe change it to EitherT[Future, String, Int] instead? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's much better actually.

@codecov-io
Copy link

codecov-io commented Aug 25, 2017

Codecov Report

Merging #1854 into master will not change coverage.
The diff coverage is n/a.

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #1854   +/-   ##
=======================================
  Coverage   94.96%   94.96%           
=======================================
  Files         241      241           
  Lines        4173     4173           
  Branches      106      106           
=======================================
  Hits         3963     3963           
  Misses        210      210

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 8458b24...5e6c408. Read the comment docs.

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.

Awesome! If CI passes, LGTM!

@LukaJCB LukaJCB mentioned this pull request Aug 25, 2017
70 tasks
Copy link
Collaborator

@peterneyens peterneyens left a comment

Choose a reason for hiding this comment

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

This looks really good @Technius, thanks. I left a few comments.


```tut:book
import scala.util.Try
import cats.syntax.either._
Copy link
Collaborator

Choose a reason for hiding this comment

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

We decide to use the uber import import cats.implicits._ in the documentation, see issue #1026.

} yield result

divisionProgramAsync("4", "2").value // Future(Right(2.0))
divisionProgramAsync("a", "b").value // Future(Left("a is not a number"))
Copy link
Collaborator

Choose a reason for hiding this comment

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

If you want to show the output, we should move these comments to a "non silent tut block", that way nobody can forget to update the comments if the code is changed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Using tut:book, it shows

divisionProgramAsync("4", "2").value
// res4: scala.concurrent.Future[Either[String,Double]] = Future(<not completed>)

divisionProgramAsync("a", "b").value
// res5: scala.concurrent.Future[Either[String,Double]] = Future(<not completed>)

which is why I opted to use the comments.

Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, doesn't hurt to do an Await.result here.

val parseResult = for {
a <- eitherA
b <- eitherB
} yield (a, b)
Copy link
Collaborator

Choose a reason for hiding this comment

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

You could write (eitherA, eitherB).tupled.

Copy link
Contributor Author

@Technius Technius Aug 26, 2017

Choose a reason for hiding this comment

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

If I were a new user, the applicative syntax wouldn't be well known to me, so I'll just replace the parseResult snippet with a pattern match on the eithers.

case l@Left(err) => Future.successful(Left(err))
(eitherA, eitherB) match {
case (Right(a), Right(b)) => divideAsync(a, b)
case (l@Left(err), _) => Future.successful(Left(err))
Copy link
Member

Choose a reason for hiding this comment

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

l is unused here, right? Why not just make it Left(err)? :)

@kailuowang
Copy link
Contributor

LGTM, I left a minor comment there but could be addressed by another PR.

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 @Technius! I left one extremely minor and nitpicky comment, but this is great!

import cats.implicits._

def parseDouble(s: String): Either[String, Double] =
Try(s.toDouble).map(Right(_)).getOrElse(Left(s"$s is not a number"))
Copy link
Contributor

Choose a reason for hiding this comment

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

Super nitpicky and unreasonable comment: s could still technically be a number that can't be represented as a Double. It might be best to leave it simple and just say "$s is not a valid double.

@ceedubs ceedubs merged commit fc709c7 into typelevel:master Sep 12, 2017
@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.

7 participants