Skip to content

Commit

Permalink
Merge pull request #1226 from ceedubs/faq-listt
Browse files Browse the repository at this point in the history
Add ListT section to FAQ
  • Loading branch information
ceedubs authored Jul 24, 2016
2 parents b9e78f5 + e3e4f42 commit b07b1b3
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
42 changes: 42 additions & 0 deletions docs/src/main/tut/faq.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ section: "faq"
* [What imports do I need?](#what-imports)
* [Why can't the compiler find implicit instances for Future?](#future-instances)
* [How can I turn my List of `<something>` into a `<something>` of a list?](#traverse)
* [Where is `ListT`?](#listt)
* [What does `@typeclass` mean?](#simulacrum)
* [What do types like `?` and `λ` mean?](#kind-projector)
* [What does `macro Ops` do? What is `cats.macros.Ops`?](#machinist)
Expand All @@ -36,6 +37,47 @@ If you have already followed the [imports advice](#what-imports) but are still g

It's really common to have a `List` of values with types like `Option`, `Xor`, or `Validated` that you would like to turn "inside out" into an `Option` (or `Xor` or `Validated`) of a `List`. The `sequence`, `sequenceU`, `traverse`, and `traverseU` methods are _really_ handy for this. You can read more about them in the [Traverse documentation]({{ site.baseurl }}/tut/traverse.html).

## <a id="listt" href="#listt"></a>Where is ListT?

There are monad transformers for various types, such as [OptionT]({{ site.baseurl }}/tut/optiont.html), so people often wonder why there isn't a `ListT`. For example, in the following example, people might reach for `ListT` to simplify making nested `map` and `exists` calls:

```tut:reset:silent
val l: Option[List[Int]] = Some(List(1, 2, 3, 4, 5))
def isEven(i: Int): Boolean = i % 2 == 0
```

```tut:book
l.map(_.map(_ + 1))
l.exists(_.exists(isEven))
```

A naive implementation of `ListT` suffers from associativity issues; see [this gist](https://gist.github.com/tpolecat/1227e22e3161b5816e014c00650f3b57) for an example. It's possible to create a `ListT` that doesn't have these issues, but it tends to be pretty inefficient. For many use-cases, [Nested](https://github.com/typelevel/cats/blob/master/core/src/main/scala/cats/data/Nested.scala) can be used to achieve the desired results.

Here is how we could achieve the effect of the previous example using `Nested`:

```tut:silent
import cats.data.Nested
import cats.implicits._
```

```tut:book
val nl = Nested(l)
nl.map(_ + 1)
nl.exists(isEven)
```

We can even perform more complicated operations, such as a `traverse` of the nested structure:

```tut:silent
import cats.data.ValidatedNel
type ErrorsOr[A] = ValidatedNel[String, A]
def even(i: Int): ErrorsOr[Int] = if (i % 2 == 0) i.validNel else s"$i is odd".invalidNel
```tut:book
nl.traverse(even)
```

## <a id="simulacrum" href="#simulacrum"></a>What does `@typeclass` mean?

Cats defines and implements numerous type classes. Unfortunately, encoding these type classes in Scala can incur a large amount of boilerplate. To address this, [Simulacrum](https://github.com/mpilquist/simulacrum) introduces `@typeclass`, a macro annotation which generates a lot of this boilerplate. This elevates type classes to a first class construct and increases the legibility and maintainability of the code. Use of simulacrum also ensures consistency in how the type classes are encoded across a project. Cats uses simulacrum wherever possible to encode type classes, and you can read more about it at the [project page](https://github.com/mpilquist/simulacrum).
Expand Down
2 changes: 1 addition & 1 deletion project/plugins.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.0")
addSbtPlugin("com.typesafe" % "sbt-mima-plugin" % "0.1.9")
addSbtPlugin("com.typesafe.sbt" % "sbt-ghpages" % "0.5.3")
addSbtPlugin("com.typesafe.sbt" % "sbt-site" % "0.8.1")
addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.4.2")
addSbtPlugin("org.tpolecat" % "tut-plugin" % "0.4.3")
addSbtPlugin("pl.project13.scala" % "sbt-jmh" % "0.2.3")
addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.8.0")
addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.2.0")
Expand Down

0 comments on commit b07b1b3

Please sign in to comment.