Skip to content

Commit

Permalink
docs: add example on composability of direct style
Browse files Browse the repository at this point in the history
  • Loading branch information
tassiluca committed Mar 22, 2024
1 parent 124f210 commit ecf1fa9
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package io.github.tassiLuca.dse.examples.gears

import scala.reflect.ClassTag

object ShowcasingDirectStyle:

object Monadic:
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext, Future}

def transform[E, T](
xs: Seq[Future[Either[E, T]]],
)(using ExecutionContext): Future[Either[E, Seq[T]]] =
import cats.implicits._
Future.sequence(xs) // Future[Seq[Either[E, T]]
.map(_.sequence) // equivalent to: _.traverse(identity)

def transform2[E, T](
xs: Seq[Future[Either[E, T]]],
)(using ec: ExecutionContext): Future[Either[E, Seq[T]]] =
val initial: Future[Either[E, List[T]]] = Future.successful(Right(List.empty[T]))
xs.foldRight(initial): (future, acc) =>
for
f <- future
a <- acc
yield a.flatMap(lst => f.map(_ :: lst))

@main def useMonadicTransform(): Unit =
given ExecutionContext = ExecutionContext.global
val xs = Seq(Future(Right("I")), Future(Right("Love")), Future(Right("Monads")))
val result = transform(xs) // transform 2 works as well
println(Await.result(result, Duration.Inf))
val ys = Seq(Future(Right("Yes")), Future(Left("Nope!")))
val result2 = transform(ys) // transform 2 works as well
println(Await.result(result2, Duration.Inf))

object Direct:
import gears.async.default.given
import gears.async.{Future, Async}
import io.github.tassiLuca.dse.boundaries.either
import io.github.tassiLuca.dse.boundaries.either.?
import io.github.tassiLuca.dse.boundaries.EitherConversions.given

def transform[E, T](xs: Seq[Future[Either[E, T]]])(using Async.Spawn): Future[Either[E, Seq[T]]] =
Future:
either:
xs.map(_.await.?)

@main def useDirectTransform(): Unit = Async.blocking:
val xs = Seq(Future(Right("I")), Future(Right("Love")), Future(Right("Monads")))
val result = transform(xs)
println(result.await)
val ys = Seq(Future(Right("Yes")), Future(Left("Nope!")))
val result2 = transform(ys)
println(result2.await)
19 changes: 19 additions & 0 deletions docs/presentation/direct-style-presentation.tex
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,25 @@ \section{Scala \texttt{gears}}
\end{table}
\end{frame}
%
\begin{frame}
\small
\begin{columns}
\column{0.6\textwidth}
\lstinputlisting[language=scala]{listings/intro/DirectComposability.scala}
\column{0.2\textwidth}
Direct style cleanly supports composability.
\end{columns}

\pause
\begin{columns}
\column{0.91\textwidth}
\lstinputlisting[language=scala]{listings/intro/MonadicComposability.scala}
\lstinputlisting[language=scala]{listings/intro/IdiomaticMonadicComposability.scala}
\column{0.1\textwidth}
Using monads is more complex to achieve the same goal.
\end{columns}
\end{frame}
%
\begin{frame}
\begin{columns}[c,onlytextwidth] % The "t" option specifies top vertical alignment
\column{.35\textwidth}
Expand Down
6 changes: 6 additions & 0 deletions docs/presentation/listings/intro/DirectComposability.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def transform[E, T](
xs: Seq[Future[Either[E, T]]]
)(using Async.Spawn): Future[Either[E, Seq[T]]] =
Future:
either:
xs.map(_.await.?)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
def transform[E, T](
xs: Seq[Future[Either[E, T]]],
)(using ExecutionContext): Future[Either[E, Seq[T]]] =
import cats.implicits._
Future.sequence(xs) // Future[Seq[Either[E, T]]
.map(_.sequence) // equivalent to: _.traverse(identity)
9 changes: 9 additions & 0 deletions docs/presentation/listings/intro/MonadicComposability.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
def transform2[E, T](
xs: Seq[Future[Either[E, T]]],
)(using ec: ExecutionContext): Future[Either[E, Seq[T]]] =
val initial: Future[Either[E, List[T]]] = Future.successful(Right(List.empty[T]))
xs.foldRight(initial): (future, acc) =>
for
f <- future
a <- acc
yield a.flatMap(lst => f.map(_ :: lst))

0 comments on commit ecf1fa9

Please sign in to comment.