I have a Play! 2 for Scala application that needs to retrieve some data in JSON format from an external service.
The Play! framework allows to make HTTP requests asynchr
Using the Scalaz library's OptionT
transformer, you should be able to turn values of type Promise[Option[A]]
into values of type OptionT[Promise, A]
.
Using Scalaz 7:
import scalaz.OptionT._
val x: OptionT[Promise, Int] = optionT(Promise.pure(Some(123)))
To use this value, for example to call map
or flatMap
on it, you will need to provide an appropriate typeclass for Promise
(Functor
for map
, Monad
for flatMap
).
Since Promise
is monadic, it should be possible to provide an instance of Monad[Promise]
. (You'll get Functor
and Applicative
for free, because the typeclasses form an inheritance hierarchy.) For example (note: I've not tested this!):
implicit val promiseMonad = new Monad[Promise] {
def point[A](a: => A): Promise[A] = Promise.pure(a)
def bind[A, B](fa: Promise[A])(f: A => Promise[B]): Promise[B] = fa flatMap f
}
As a simple example, you can now use map
on the OptionT[Promise, A]
, to apply a function of type A => B
to the value inside:
def foo[A, B](x: OptionT[Promise, A], f: A => B): OptionT[Promise, B] = x map f
To retrieve the underlying Promise[Option[A]]
value from an OptionT[Promise, A]
, call the run
method.
def bar[A, B](x: Promise[Option[A]], f: A => B): Promise[Option[B]] =
optionT(x).map(f).run
You will gain more benefit from using monad transformers when you can compose several operations of compatible types, preserving the OptionT[Promise, _]
type between operations and retrieving the underlying value at the end.
To compose operations in a for-comprehension, you will need functions of type A => OptionT[Promise, B]
.
-- removed --
edit:
Okay, you can simply use the scalaz.OptionT
here:
val x = optionT(Promise { /* api call */ some("""{ "foo": "bar" }""") })
val mapped = x.map(Json.parse).run // run return the resulting Promise[Option[T]]