Dumonad is a solution to ease of using monad in Scala projects with introducing a set of extension methods and wrapper types.
KISS your code with Dumonad!
Reactive programming become more and more popular nowadays. A common response of a reactive call is a nested monad
(i.e. Future[Either[L,R]]
or Future[Option[T]]
)
All scala developers know what are map
, flatmap
, and flatten
The shortest way of chaining two Future[Either[L,R]]
using standard Scala API will be something like this:
def firstCall: Future[Either[String, String]] = ???
def secondCall(param: String): Future[Either[String, String]] = ???
val result: Future[Either[String, String]] = firstCall.flatMap {
case Right(value) => secondCall(value)
case left => Future.successful(left)
}
While using Dumonad it will be easier empowered with dumap
:
def firstCall: Future[Either[String, String]]
def secondCall(param: String): Future[Either[String, String]]
val result: Future[Either[String, String]] = firstCall.dumap(secondCall)
Beside extension methods, Dumonad also represents a set of wrapper classes for nested types(FutureOption
,FutureEither
,...)
To wrap the base model you can use apply
method or related extension method:
import io.github.dumonad.dumonad.future.FutureEither
val maybeCustomer: Future[Option[Customer]]
def persistCustomer(customer: Customer): Future[Either[String, PersistResult]]
for {
customer <- maybeCustomer.toFutureRight("customer not found")
persistResult <- persistCustomer(customer).toFutureeither
} yield persistResult
Another thing is changing the order of monad wrappers.
Developers usually use boilerplate codes to do this. For example:
val optionOfFuture: Option[Future[String]]
val futureOfOption: Future[Option[String]] = optionOfFuture match {
case Some(future) => future.map(Some(_))
case _ => Future.successful(None)
}
With extractFuture
method it will be a piece of cake, because in Dumonad Future
is always the outer wrapper.
val optionOfFuture: Option[Future[String]]
val futureOfOption: Future[Option[String]] = optionOfFuture.extractFuture
Another helper method is extractEither
that converts Seq[Either[L,R]]
to Either[Seq[L],Seq[R]]
supported scala versions : 2.12, 2.13, and 3.0
Add the dependency in build.sbt
libraryDependencies += "io.github.dumonad" %% "dummonad" % "0.5"
It's all set!
import io.github.dumonad.dumonad.Implicits._
validate(customer).dumap(persist).dumap(notifyAdmin)