Applicative functors are often mentioned as an alternative to monads when your computation steps are independent. One of their often-mentioned advantages is that you don't need transformers when you want to stack applicatives, because F[G[X]] is always also an applicative.
Let's say I have following functions:
def getDataOption(): Option[Data]
def getUserFuture(): Future[User]
def process(data: Data, user: User)
I would like to have elegant stacking in order to get a Future[Option[User]] and Future[Option[Data]] and map that with process.
So far I only came up with this (using Cats):
Applicative[Future]
.compose[Option]
.map2(
Applicative[Future].pure(getDataOption()),
getUserFuture().map(Applicative[Option].pure))(process)
but I'm sure it's far from ideal. Is there a more elegant and generic way to achieve the same?
The most difficult thing is type inference here. This is the best I could do
// for the Applicative[Future[Option[?]]
import cats.Applicative
implicit val fo = {
import cats.std.future._
import cats.std.option._
Applicative[Future].compose[Option]
}
// for the |#| syntax
import cats.syntax.cartesian._
// to guide type inference
type FutureOption[A] = Future[Option[A]]
((Future(getDataOption): FutureOption[Data]) |#|
getUserFuture.map(Option.apply)).map(process _)
Related
If we have such two functions...
def findUserById(id: Long): Future[Option[User]] = ???
def findAddressByUser(user: User): Future[Option[Address]] = ???
...then we are able to use cats OptionT monad transformer to write for-comprehension with them easily:
for {
user <- OptionT(findUserById(id))
address <- OptionT(findAddressByUser(user))
} ...
I'd like to compose future of sequences this way, like this:
def findUsersBySomeField(value: FieldValue): Future[Seq[User]] = ???
def findAddressesByUser(user: User): Future[Seq[Address]] = ???
for {
user <- SeqT(findUsersBySomeField(value))
address <- SeqT(findAddressesByUser(user))
} ...
But I can't find any SeqT implementation in Cats or Scalaz. Does some implementation of such monad transformer exist or I need to write monad transformer myself? Not that it too hard, just don't want to reinvent the wheel.
(example at the beginning of my question is brought from this article)
Cats, as of 1.0.0-MF have nothing of sorts. That is explained at their FAQ:
A naive implementation of ListT suffers from associativity issues; see this gist 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 can be used to achieve the desired results.
Scalaz, as of 7.2.15 has StreamT and ListT, although the latter has associativity issues.
I am trying to validate a list of strings sequentially and define the validation result type like that:
import cats._, cats.data._, cats.implicits._
case class ValidationError(msg: String)
type ValidationResult[A] = Either[NonEmptyList[ValidationError], A]
type ListValidationResult[A] = ValidationResult[List[A]] // not a monad :(
I would like to make ListValidationResult a monad. Should I implement flatMap and pure manually or there is an easier way ?
I suggest you to take a totally different approach leveraging cats Validated:
import cats.data.Validated.{ invalidNel, valid }
val stringList: List[String] = ???
def evaluateString(s: String): ValidatedNel[ValidationError, String] =
if (???) valid(s) else invalidNel(ValidationError(s"invalid $s"))
val validationResult: ListValidationResult[String] =
stringList.map(evaluateString).sequenceU.toEither
It can be adapted for a generic type T, as per your example.
Notes:
val stringList: List[String] = ??? is the list of strings you want to validate;
ValidatedNel[A,B] is just a type alias for Validated[NonEmptyList[A],B];
evaluateString should be your evaluation function, it is currently just an unimplemented stub if;
sequenceU you may want to read cats documentation about it: sequenceU;
toEither does exactly what you think it does, it converts a Validated[A,B] to an Either[A,B].
As #Michael pointed out, you could also use traverseU instead of map and sequenceU
val validationResult: ListValidationResult[String] =
stringList.traverseU(evaluateString).toEither
I'm trying to wrap my head around the free monads (and transformers). I've been able to construct my own free monad using scalaz.FreeT and an interpreter that runs it into a seemingly arbitrary monad by first naively hoisting into target monad and then running the free monad, like this:
import scalaz._
import Scalaz._
type MyCoolMonad[A] = FreeT[SomeFunctor, Id, A]
type ResultMonad[A] = ??? // for example Id[A]
def id2monadNT[R[_]: Monad]: (id ~> R) = {
override def apply[A](fa: A) = fa.point[R]
} // for hoisting
val myInterpreter = new (SomeFunctor ~> ResultMonad) {
override def apply[A](fa: SomeFuntor[A]) = {...} // the meat is here
}
def runCoolMonad[A](m: MyCoolMonad[A]) =
m.hoistN(id2monadNT[R]).runM(myInterpreter.apply)
So, the first and less important question is, do I have to do the hoisting in oder to run the free monad into other arbitrary monad? It seems somehow excessive...
And the main course: the .runM requires ResultMonad to provide a BindRec instance which proves that one can bind over ResultMonad in constant stack space. I would like to have an interpreter that runs my free monad using scala.concurrent.Future as a result - and that is not stack safe. Is there any way to do that? I know that I give up on a certain guarantee, but as the dev I can have the confidence that Future.flatMap stack won't be deep enough to cause any trouble (we're using plain Futures without free monads everywhere and it works fine)
I'm using Scalaz 7.2.1, which to my knowledge is the most recent.
Sidenote: I am aware of scalaz.concurrent.Task existence, and I would still like to know how to interpret free monad into scala.concurrent.Future.
To answer your first question: If you only have FreeT[SomeFunctor, Id, A], it is equivalent to Free[SomeFunctor, A]. Then given SomeFunctor ~> Future, you can interpret the Free[SomeFunctor, A] to Future[A]. I.e. no need for FreeT and hoisting. Also, Free allows you to interpret to any monad.
FreeT is a more recent addition to scalaz. While Free was first designed to interpret to any monad and the stack-safe versions of operations were only added later, FreeT from the beginning supports only stack-safe monads.
If you still want to use FreeT with scala.concurrent.Future, just provide a BindRec instance.
implicit def futureBindRec: BindRec[Future] = new BindRec[Future] {
def tailrecM[A, B](f: A => Future[A \/ B])(a: A): Future[B] =
f(a) flatMap {
case -\/(a1) => tailrecM(f)(a1)
case \/-(b) => Future(b)
}
def map...
def bind...
}
This might even be stack safe, if Future#flatMap(f) never calls f eagerly (which maybe it does on a completed Future, but I'm not familiar enough with it to tell).
For example, there are two classes: A and B. And there is a method in A called toB.
Now there is a value a which is of type Future[Option[A]], what will be the most elegant way to convert it to Future[Option[B]]?
Currently I'm using a.map(_.map(_.toB)), but I think it looks a bit clumsy and confusing. Does anyone have better ways to do this? (implicit conversion)
Thanks!
If you need to operate a lot on the "stack" of Future[Option[?]] you can use a monad transformer:
val a: OptionT[Future, A] = OptionT(...)
val b: OptionT[Future, B] = a.map(_.toB)
If you're willing to throw some scalaz in there, you could write a generic function for this:
import scalaz._
import Scalaz._
def mapF[F[_]: Functor, G[_]:Functor,A,B](fg: F[G[A]], h : A => B) : F[G[B]] = fg.map( _.map(h))
It uses the "ugly" mapmap version, but it would work for any Functor.
If you want to use it infix, just create an implicit class for it:
implicit class toMapF[F[_]:Functor,G[_]:Functor, A](fg : F[G[A]]){
def mapF[B](f: A => B) = fg.map( _.map(f))
}
Then you can use it like:
a.mapF(_.toB)
This is of course absolute overkill unless you're already using scalaz, but any reason is good to try it out.
Why and how specifically is a Scala Future not a Monad; and would someone please compare it to something that is a Monad, like an Option?
The reason I'm asking is Daniel Westheide's The Neophyte's Guide to Scala Part 8: Welcome to the Future where I asked whether or not a Scala Future was a Monad, and the author responded that it wasn't, which threw off base. I came here to ask for a clarification.
A summary first
Futures can be considered monads if you never construct them with effectful blocks (pure, in-memory computation), or if any effects generated are not considered as part of semantic equivalence (like logging messages). However, this isn't how most people use them in practice. For most people using effectful Futures (which includes most uses of Akka and various web frameworks), they simply aren't monads.
Fortunately, a library called Scalaz provides an abstraction called Task that doesn't have any problems with or without effects.
A monad definition
Let's review briefly what a monad is. A monad must be able to define at least these two functions:
def unit[A](block: => A)
: Future[A]
def bind[A, B](fa: Future[A])(f: A => Future[B])
: Future[B]
And these functions must statisfy three laws:
Left identity: bind(unit(a))(f) ≡ f(a)
Right identity: bind(m) { unit(_) } ≡ m
Associativity: bind(bind(m)(f))(g) ≡ bind(m) { x => bind(f(x))(g) }
These laws must hold for all possible values by definition of a monad. If they don't, then we simply don't have a monad.
There are other ways to define a monad that are more or less the same. This one is popular.
Effects lead to non-values
Almost every usage of Future that I've seen uses it for asychronous effects, input/output with an external system like a web service or a database. When we do this, a Future isn't even a value, and mathematical terms like monads only describe values.
This problem arises because Futures execute immediately upon data contruction. This messes up the ability to substitute expressions with their evaluated values (which some people call "referential transparency"). This is one way to understand why Scala's Futures are inadequate for functional programming with effects.
Here's an illustration of the problem. If we have two effects:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits._
def twoEffects =
( Future { println("hello") },
Future { println("hello") } )
we will have two printings of "hello" upon calling twoEffects:
scala> twoEffects
hello
hello
scala> twoEffects
hello
hello
But if Futures were values, we should be able to factor out the common expression:
lazy val anEffect = Future { println("hello") }
def twoEffects = (anEffect, anEffect)
But this doesn't give us the same effect:
scala> twoEffects
hello
scala> twoEffects
The first call to twoEffects runs the effect and caches the result, so the effect isn't run the second time we call twoEffects.
With Futures, we end up having to think about the evaluation policy of the language. For instance, in the example above, the fact I use a lazy value rather than a strict one makes a difference in the operational semantics. This is exactly the kind of twisted reasoning functional programming is designed to avoid -- and it does it by programming with values.
Without substitution, laws break
In the presense of effects, monad laws break. Superficially, the laws appear to hold for simple cases, but the moment we begin to substitute expressions with their evaluated values, we end up with the same problems we illustrated above. We simply can't talk about mathematical concepts like monads when we don't have values in the first place.
To put it bluntly, if you use effects with your Futures, saying they're monads is not even wrong because they aren't even values.
To see how monad laws break, just factor out your effectful Future:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits._
def unit[A]
(block: => A)
: Future[A] =
Future(block)
def bind[A, B]
(fa: Future[A])
(f: A => Future[B])
: Future[B] =
fa flatMap f
lazy val effect = Future { println("hello") }
Again, it will only run one time, but you need it to run twice -- once for the right-hand side of the law, and another for the left. I'll illustrate the problem for the right identity law:
scala> effect // RHS has effect
hello
scala> bind(effect) { unit(_) } // LHS doesn't
The implicit ExecutionContext
Without putting an ExecutionContext in implicit scope, we can't define either unit or bind in our monad. This is because the Scala API for Futures has these signature:
object Future {
// what we need to define unit
def apply[T]
(body: ⇒ T)
(implicit executor: ExecutionContext)
: Future[T]
}
trait Future {
// what we need to define bind
flatMap[S]
(f: T ⇒ Future[S])
(implicit executor: ExecutionContext)
: Future[S]
}
As a "convenience" to the user, the standard library encourages users to define an execution context in implicit scope, but I think this is a huge hole in the API that just leads to defects. One scope of the computation may have one execution context defined while another scope can have another context defined.
Perhaps you can ignore the problem if you define an instance of unit and bind that pins both operations to a single context and use this instance consistently. But this is not what people do most of the time. Most of the time, people use Futures with for-yield comprehensions that become map and flatMap calls. To make for-yield comprehensions work, an execution context must be defined at some non-global implicit scope (because for-yield doesn't provide a way to specify additional parameters to the map and flatMap calls).
To be clear, Scala lets you use lots of things with for-yield comprehensions that aren't actually monads, so don't believe that you have a monad just because it works with for-yield syntax.
A better way
There's a nice library for Scala called Scalaz that has an abstraction called scalaz.concurrent.Task. This abstraction doesn't run effects upon data construction as the standard library Future does. Furthermore, Task actually is a monad. We compose Task monadically (we can use for-yield comprehensions if we like), and no effects run while we're composing. We have our final program when we have composed a single expression evaluating to Task[Unit]. This ends up being our equivalent of a "main" function, and we can finally run it.
Here's an example illustrating how we can substitute Task expressions with their respective evaluated values:
import scalaz.concurrent.Task
import scalaz.IList
import scalaz.syntax.traverse._
def twoEffects =
IList(
Task delay { println("hello") },
Task delay { println("hello") }).sequence_
We will have two printings of "hello" upon calling twoEffects:
scala> twoEffects.run
hello
hello
And if we factor out the common effect,
lazy val anEffect = Task delay { println("hello") }
def twoEffects =
IList(anEffect, anEffect).sequence_
we get what we'd expect:
scala> twoEffects.run
hello
hello
In fact, it doesn't really matter that whether we use a lazy value or a strict value with Task; we get hello printed out twice either way.
If you want to functionally program, consider using Task everywhere you may use Futures. If an API forces Futures upon you, you can convert the Future to a Task:
import concurrent.
{ ExecutionContext, Future, Promise }
import util.Try
import scalaz.\/
import scalaz.concurrent.Task
def fromScalaDeferred[A]
(future: => Future[A])
(ec: ExecutionContext)
: Task[A] =
Task
.delay { unsafeFromScala(future)(ec) }
.flatMap(identity)
def unsafeToScala[A]
(task: Task[A])
: Future[A] = {
val p = Promise[A]
task.runAsync { res =>
res.fold(p failure _, p success _)
}
p.future
}
private def unsafeFromScala[A]
(future: Future[A])
(ec: ExecutionContext)
: Task[A] =
Task.async(
handlerConversion
.andThen { future.onComplete(_)(ec) })
private def handlerConversion[A]
: ((Throwable \/ A) => Unit)
=> Try[A]
=> Unit =
callback =>
{ t: Try[A] => \/ fromTryCatch t.get }
.andThen(callback)
The "unsafe" functions run the Task, exposing any internal effects as side-effects. So try not to call any of these "unsafe" functions until you've composed one giant Task for your entire program.
I believe a Future is a Monad, with the following definitions:
def unit[A](x: A): Future[A] = Future.successful(x)
def bind[A, B](m: Future[A])(fun: A => Future[B]): Future[B] = fut.flatMap(fun)
Considering the three laws:
Left identity:
Future.successful(a).flatMap(f) is equivalent to f(a). Check.
Right identity:
m.flatMap(Future.successful _) is equivalent to m (minus some possible performance implications). Check.
Associativity
m.flatMap(f).flatMap(g) is equivalent to m.flatMap(x => f(x).flatMap(g)). Check.
Rebuttal to "Without substitution, laws break"
The meaning of equivalent in the monad laws, as I understand it, is you could replace one side of the expression with the other side in your code without changing the behavior of the program. Assuming you always use the same execution context, I think that is the case. In the example #sukant gave, it would have had the same issue if it had used Option instead of Future. I don't think the fact that the futures are evaluated eagerly is relevant.
As the other commenters have suggested, you are mistaken. Scala's Future type has the monadic properties:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits._
def unit[A](block: => A): Future[A] = Future(block)
def bind[A, B](fut: Future[A])(fun: A => Future[B]): Future[B] = fut.flatMap(fun)
This is why you can use for-comprehension syntax with futures in Scala.