Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Scalaz integration for Play 2.0
Branch: master

Scalaz integration for Play 2.0


Add play-scalaz to your project/Build.scala file

val appDependencies = Seq(
  "eu.teamon" %% "play-scalaz" % "0.1.2-SNAPSHOT"

val main = PlayProject(appName, appVersion, appDependencies, mainLang = SCALA).settings(
  resolvers += "scalajars repo" at ""


Json deserialization

Play's default json API:

trait Reads[A] {
  def reads(js: JsValue): A
}[A]    // A or Exception
someJson.asOpt[A] // Option[A]

will throw exception in case of invalid json input, or when using asOpt will return Option[A] which contains no information about what went wrong.

play-scalaz provides

trait Readz[A] {
  def reads(js: JsValue): Validation[NonEmptyList[String], A]

case class Foo(a: Int, b: String)

implicit val FooReadz = readz2("a", "b")(Foo)

fromJson[Foo](someJson) // Validation[NonEmptyList[String], Foo]

which will return either the value or list of errors

Promise Monad

Let's say there is code like:

def authenticate(code: String): Promise[Option[Projects]] = requestAccessToken(code).flatMap { tokenOpt => { token => 
    requestAccessToken(token).flatMap { userOpt => { user =>
      } getOrElse Promise.pure(None)
  } getOrElse Promise.pure(None)

def requestAccessToken(code: String): Promise[Option[String]]
def requestUserInfo(accessToken: String): Promise[Option[UserInfo]]
def requestProjects(user: UserInfo): Promise[Option[Projects]]

it gets even more bloated when number of calls grows. But with Promise being Monad:

def authenticate(code: String): Promise[Option[UserInfo]] = (for {
  accessToken <- OptionT(requestAccessToken(code))
  userInfo    <- OptionT(requestUserInfo(accessToken))
  projects    <- OptionT(requestProject(userInfo))
} yield projects).run


Something went wrong with that request. Please try again.