Skip to content

Commit

Permalink
address comments from @armanbilge
Browse files Browse the repository at this point in the history
  • Loading branch information
gatear committed Dec 9, 2021
1 parent 030405c commit d4d97b2
Showing 1 changed file with 21 additions and 14 deletions.
35 changes: 21 additions & 14 deletions docs/src/main/mdoc/typeclasses/bimonad.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,34 @@ scaladoc: "#cats.Bimonad"
---
# Bimonad

The `Bimonad` trait directly extends `Monad` and `Comonad` without introducing new behaviour. `Bimonad` is
different of other `Bi` typeclasses like `Bifunctor`, `Bifoldable` or `Bitraverse` where the prefix describes a
`F[_, _]`. The `Bimonad` is a `F[_]` and could be better seen as a dual monad i.e. something that is both a `Monad` and
a `Comonad`.
The `Bimonad` trait directly extends `Monad` and `Comonad` without introducing new methods. `Bimonad` is
different from other `Bi` typeclasses like `Bifunctor`, `Bifoldable` or `Bitraverse` where the prefix describes a
`F[_, _]`. The `Bimonad` is a `F[_]` and the `Bi` prefix has a different meaning here: it's both a `Monad` and a `Comonad`.

If you use `Bimonad` as a convenience type such that `def f[T[_] : Monad, Comonad, S](fa: T[S]): S` is re-written to
`def f[T[_] : Bimonad, S](fa: T[S]): S` keep in mind `Bimonad` has its own added laws so something that is both monadic

If you use `Bimonad` as a convenience type such that:
```scala
def f[T[_] : Monad, Comonad, S](fa: T[S]): S
```
is re-written to:
```scala
def f[T[_] : Bimonad, S](fa: T[S]): S
```
keep in mind `Bimonad` has its own added laws so something that is both monadic
and comonadic may not necessarily be a lawful `Bimonad`.

###Eval as a Bimonad
Eval is a lawful `Bimonad` so you can chain computations and `extract` the result at the end.
Eval is a lawful `Bimonad` so you can chain computations (like a `Monad`) and `extract` the result at the end (like a `Comonad`).

Note the equivalence:
```scala mdoc
import cats._
import cats.data._
import cats.implicits._

Bimonad[Eval].pure(true).extract === Eval.now(true).value
val evalBimonad = Bimonad[Eval]

evalBimonad.pure(true).extract === Eval.now(true).value
```

Using generic bimonad syntax we could define a function that appends and extracts a configuration:
Expand All @@ -41,15 +50,13 @@ def make[T[_]: Bimonad](config: T[String]): String =
This will work with all types of `Eval`:
```scala mdoc
make(Eval.now("config"))
make(Eval.later("config"))

//String = config with option A with option B with option C
make(Eval.later("config"))
```

Given that `Function0` or `NonEmptyList` are also lawful bimonads the following calls are also valid:
`Function0` and `NonEmptyList` are also lawful bimonads so the following calls are also valid:
```scala mdoc
make(() => "config")
make(NonEmptyList.one("config"))

//String = config with option A with option B with option C
```
make(NonEmptyList.one("config"))
```

0 comments on commit d4d97b2

Please sign in to comment.