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

make tut doc ever so slightly less hideous #709

Merged
merged 1 commit into from
Dec 3, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions docs/src/main/tut/apply.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ a context can be `Option`, `List` or `Future` for example).
However, the difference between `ap` and `map` is that for `ap` the function that
takes care of the transformation is of type `F[A => B]`, whereas for `map` it is `A => B`:

```tut
```tut:silent
import cats._

val intToString: Int => String = _.toString
val double: Int => Int = _ * 2
val addTwo: Int => Int = _ + 2
Expand Down Expand Up @@ -133,8 +134,6 @@ f2(Some(1), Some(2), Some(3))
All instances created by `|@|` have `map`, `ap`, and `tupled` methods of the appropriate arity:

```tut
import cats.syntax.apply._

val option2 = Option(1) |@| Option(2)
val option3 = option2 |@| Option.empty[Int]

Expand Down
26 changes: 13 additions & 13 deletions docs/src/main/tut/const.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ have its uses, which serve as a nice example of the consistency and elegance of
## Thinking about `Const`
The `Const` data type can be thought of similarly to the `const` function, but as a data type.

```tut
```tut:silent
def const[A, B](a: A)(b: => B): A = a
```

The `const` function takes two arguments and simply returns the first argument, ignoring the second.

```scala
```tut:silent
final case class Const[A, B](getConst: A)
```

Expand All @@ -44,7 +44,7 @@ to use a lens.
A lens can be thought of as a first class getter/setter. A `Lens[S, A]` is a data type that knows how to get
an `A` out of an `S`, or set an `A` in an `S`.

```tut
```tut:silent
trait Lens[S, A] {
def get(s: S): A

Expand All @@ -58,7 +58,7 @@ trait Lens[S, A] {
It can be useful to have effectful modifications as well - perhaps our modification can fail (`Option`) or
can return several values (`List`).

```tut
```tut:silent
trait Lens[S, A] {
def get(s: S): A

Expand All @@ -78,7 +78,7 @@ trait Lens[S, A] {
Note that both `modifyOption` and `modifyList` share the *exact* same implementation. If we look closely, the
only thing we need is a `map` operation on the data type. Being good functional programmers, we abstract.

```tut
```tut:silent
import cats.Functor
import cats.syntax.functor._

Expand All @@ -99,7 +99,7 @@ We can redefine `modify` in terms of `modifyF` by using `cats.Id`. We can also t
that simply ignores the current value. Due to these modifications however, we must leave `modifyF` abstract
since having it defined in terms of `set` would lead to infinite circular calls.

```tut
```tut:silent
import cats.Id

trait Lens[S, A] {
Expand Down Expand Up @@ -134,7 +134,7 @@ is to take an `A` and return it right back (lifted into `Const`).
Before we plug and play however, note that `modifyF` has a `Functor` constraint on `F[_]`. This means we need to
define a `Functor` instance for `Const`, where the first type parameter is fixed.

```tut
```tut:silent
import cats.data.Const

implicit def constFunctor[X]: Functor[Const[X, ?]] =
Expand All @@ -147,7 +147,7 @@ implicit def constFunctor[X]: Functor[Const[X, ?]] =

Now that that's taken care of, let's substitute and see what happens.

```tut
```tut:silent
trait Lens[S, A] {
def modifyF[F[_] : Functor](s: S)(f: A => F[A]): F[S]

Expand All @@ -174,7 +174,7 @@ In the popular [The Essence of the Iterator Pattern](https://www.cs.ox.ac.uk/jer
paper, Jeremy Gibbons and Bruno C. d. S. Oliveria describe a functional approach to iterating over a collection of
data. Among the abstractions presented are `Foldable` and `Traverse`, replicated below (also available in Cats).

```tut
```tut:silent
import cats.{Applicative, Monoid}

trait Foldable[F[_]] {
Expand All @@ -194,7 +194,7 @@ These two type classes seem unrelated - one reduces a collection down to a singl
a collection with an effectful function, collecting results. It may be surprising to see that in fact `Traverse`
subsumes `Foldable`.

```tut
```tut:silent
trait Traverse[F[_]] extends Foldable[F] {
def traverse[G[_] : Applicative, A, X](fa: F[A])(f: A => G[X]): G[F[X]]

Expand All @@ -211,7 +211,7 @@ However, if we imagine `G[_]` to be a sort of type-level constant function, wher
`F[X]` is the value we want to ignore, we treat it as the second type parameter and hence, leave it as the free
one.

```tut
```tut:silent
import cats.data.Const

implicit def constApplicative[Z]: Applicative[Const[Z, ?]] =
Expand All @@ -235,7 +235,7 @@ should try to do something more useful. This suggests composition of `Z`s, which
So now we need a constant `Z` value, and a binary function that takes two `Z`s and produces a `Z`. Sound familiar?
We want `Z` to have a `Monoid` instance!

```tut
```tut:silent
implicit def constApplicative[Z : Monoid]: Applicative[Const[Z, ?]] =
new Applicative[Const[Z, ?]] {
def pure[A](a: A): Const[Z, A] = Const(Monoid[Z].empty)
Expand All @@ -261,7 +261,7 @@ So to summarize, what we want is a function `A => Const[B, Nothing]`, and we hav
that `Const[B, Z]` (for any `Z`) is the moral equivalent of just `B`, so `A => Const[B, Nothing]` is equivalent
to `A => B`, which is exactly what we have, we just need to wrap it.

```tut
```tut:silent
trait Traverse[F[_]] extends Foldable[F] {
def traverse[G[_] : Applicative, A, X](fa: F[A])(f: A => G[X]): G[F[X]]

Expand Down
12 changes: 9 additions & 3 deletions docs/src/main/tut/foldable.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@ used by the associated `Foldable[_]` instance.
These form the basis for many other operations, see also:
[A tutorial on the universality and expressiveness of fold](https://www.cs.nott.ac.uk/~gmh/fold.pdf)

```tut
First some standard imports.

```tut:silent
import cats._
import cats.std.all._
```

And examples.

```tut
Foldable[List].fold(List("a", "b", "c"))
Foldable[List].foldMap(List(1, 2, 4))(_.toString)
Foldable[List].foldK(List(List(1,2,3), List(2,3,4)))
Expand Down Expand Up @@ -70,13 +76,13 @@ Hence when defining some new data structure, if we can define a `foldLeft` and
Note that, in order to support laziness, the signature of `Foldable`'s
`foldRight` is

```
```scala
def foldRight[A, B](fa: F[A], lb: Eval[B])(f: (A, Eval[B]) => Eval[B]): Eval[B]
```

as opposed to

```
```scala
def foldRight[A, B](fa: F[A], z: B)(f: (A, B) => B): B
```

Expand Down
12 changes: 6 additions & 6 deletions docs/src/main/tut/functor.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,13 @@ Vector(1,2,3).map(_.toString)
We can trivially create a `Functor` instance for a type which has a well
behaved `map` method:

```tut
```tut:silent
import cats._

implicit val optionFunctor: Functor[Option] = new Functor[Option] {
def map[A,B](fa: Option[A])(f: A => B) = fa map f
}

implicit val listFunctor: Functor[List] = new Functor[List] {
def map[A,B](fa: List[A])(f: A => B) = fa map f
}
Expand All @@ -48,7 +50,7 @@ However, functors can also be created for types which don't have a `map`
method. For example, if we create a `Functor` for `Function1[In, ?]`
we can use `andThen` to implement `map`:

```tut
```tut:silent
implicit def function1Functor[In]: Functor[Function1[In, ?]] =
new Functor[Function1[In, ?]] {
def map[A,B](fa: In => A)(f: A => B): Function1[In,B] = fa andThen f
Expand Down Expand Up @@ -79,10 +81,8 @@ Functor[List].map(List("qwer", "adsfg"))(len)
is a `Some`:

```tut
// Some(x) case: function is applied to x; result is wrapped in Some
Functor[Option].map(Some("adsf"))(len)
// None case: simply returns None (function is not applied)
Functor[Option].map(None)(len)
Functor[Option].map(Some("adsf"))(len) // Some(x) case: function is applied to x; result is wrapped in Some
Functor[Option].map(None)(len) // None case: simply returns None (function is not applied)
```

## Derived methods
Expand Down
29 changes: 16 additions & 13 deletions docs/src/main/tut/kleisli.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,26 @@ One of the most useful properties of functions is that they **compose**. That is
this compositional property that we are able to write many small functions and compose them together
to create a larger one that suits our needs.

```tut
```tut:silent
val twice: Int => Int =
x => x * 2

val countCats: Int => String =
x => if (x == 1) "1 cat" else s"$x cats"

val twiceAsManyCats: Int => String =
twice andThen countCats
// equivalent to: countCats compose twice
twice andThen countCats // equivalent to: countCats compose twice
```

Thus.

```tut
twiceAsManyCats(1) // "2 cats"
```

Sometimes, our functions will need to return monadic values. For instance, consider the following set of functions.

```tut
```tut:silent
val parse: String => Option[Int] =
s => if (s.matches("-?[0-9]+")) Some(s.toInt) else None

Expand All @@ -58,7 +61,7 @@ properties of the `F[_]`, we can do different things with `Kleisli`s. For instan
`FlatMap[F]` instance (we can call `flatMap` on `F[A]` values), we can
compose two `Kleisli`s much like we can two functions.

```tut
```tut:silent
import cats.FlatMap
import cats.syntax.flatMap._

Expand All @@ -70,7 +73,7 @@ final case class Kleisli[F[_], A, B](run: A => F[B]) {

Returning to our earlier example:

```tut
```tut:silent
// Bring in cats.FlatMap[Option] instance
import cats.std.option._

Expand All @@ -87,7 +90,7 @@ It is important to note that the `F[_]` having a `FlatMap` (or a `Monad`) instan
we can do useful things with weaker requirements. Such an example would be `Kleisli#map`, which only requires
that `F[_]` have a `Functor` instance (e.g. is equipped with `map: F[A] => (A => B) => F[B]`).

```tut
```tut:silent
import cats.Functor

final case class Kleisli[F[_], A, B](run: A => F[B]) {
Expand Down Expand Up @@ -117,7 +120,7 @@ resolution will pick up the most specific instance it can (depending on the `F[_

An example of a `Monad` instance for `Kleisli` would be:

```tut
```tut:silent
import cats.syntax.flatMap._
import cats.syntax.functor._
// Alternatively we can import cats.implicits._ to bring in all the
Expand Down Expand Up @@ -179,7 +182,7 @@ That is, we take a read-only value, and produce some value with it. For this rea
functions often refer to the function as a `Reader`. For instance, it is common to hear about the `Reader` monad.
In the same spirit, Cats defines a `Reader` type alias along the lines of:

```tut
```tut:silent
// We want A => B, but Kleisli provides A => F[B]. To make the types/shapes match,
// we need an F[_] such that providing it a type A is equivalent to A
// This can be thought of as the type-level equivalent of the identity function
Expand Down Expand Up @@ -210,7 +213,7 @@ Let's look at some example modules, where each module has it's own configuration
If the configuration is good, we return a `Some` of the module, otherwise a `None`. This example uses `Option` for
simplicity - if you want to provide error messages or other failure context, consider using `Xor` instead.

```tut
```tut:silent
case class DbConfig(url: String, user: String, pass: String)
trait Db
object Db {
Expand All @@ -229,7 +232,7 @@ data over the web). Both depend on their own configuration parameters. Neither k
should be. However our application needs both of these modules to work. It is plausible we then have a more global
application configuration.

```tut
```tut:silent
case class AppConfig(dbConfig: DbConfig, serviceConfig: ServiceConfig)

class App(db: Db, service: Service)
Expand All @@ -239,7 +242,7 @@ As it stands, we cannot use both `Kleisli` validation functions together nicely
other a `ServiceConfig`. That means the `FlatMap` (and by extension, the `Monad`) instances differ (recall the
input type is fixed in the type class instances). However, there is a nice function on `Kleisli` called `local`.

```tut
```tut:silent
final case class Kleisli[F[_], A, B](run: A => F[B]) {
def local[AA](f: AA => A): Kleisli[F, AA, B] = Kleisli(f.andThen(run))
}
Expand All @@ -251,7 +254,7 @@ so long as we tell it how to go from an `AppConfig` to the other configs.

Now we can create our application config validator!

```tut
```tut:silent
final case class Kleisli[F[_], Z, A](run: Z => F[A]) {
def flatMap[B](f: A => Kleisli[F, Z, B])(implicit F: FlatMap[F]): Kleisli[F, Z, B] =
Kleisli(z => F.flatMap(run(z))(a => f(a).run(z)))
Expand Down
6 changes: 3 additions & 3 deletions docs/src/main/tut/monad.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ We can use `flatten` to define `flatMap`: `flatMap` is just `map`
followed by `flatten`. Conversely, `flatten` is just `flatMap` using
the identity function `x => x` (i.e. `flatMap(_)(x => x)`).

```tut
```tut:silent
import cats._

implicit def optionMonad(implicit app: Applicative[Option]) =
Expand All @@ -52,7 +52,7 @@ implicit def optionMonad(implicit app: Applicative[Option]) =
follows this tradition by providing implementations of `flatten` and `map`
derived from `flatMap` and `pure`.

```tut
```tut:silent
implicit val listMonad = new Monad[List] {
def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f)
def pure[A](a: A): List[A] = List(a)
Expand Down Expand Up @@ -94,7 +94,7 @@ instructions on how to compose any outer monad (`F` in the following
example) with a specific inner monad (`Option` in the following
example).

```tut
```tut:silent
case class OptionT[F[_], A](value: F[Option[A]])

implicit def optionTMonad[F[_]](implicit F : Monad[F]) = {
Expand Down
Loading