xebia-functional / scala-commons-47

An heterogeneous collection of Scala related utils, traits and classes

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Scala Commons 47 (ARCHIVED)

ScalaZ Monad Utils

This repository defines an heterogeneous collection of Scala related utils, traits and classes, to ease the use of the ScalaZ library.

OptionTFutureConversion

Allows mixing heterogeneous expressions in for comprehensions without the need for nested flatmaps or nested for - yield. Uses Scalaz OptionT to resolve Future[Option] expressions into their flattened values.

Consider a case where you have the need to pass values from functions with heterogeneous result types and that are somewhat chained or dependent in a list of operations.

def fetchSample1: Future[Option[Int]] = ???

def fetchSample2(sample1: Int): Future[Option[Int]] = ???

def compute(a: Int, b: Int): Option[Int] = ???

def anotherAsyncComputation(previousComputation: Int): Future[Int] = ???

In plain Scala you may chain nested flatMap calls to keep the types compatible...

def plainScalaImpl: Future[Option[Int]] = fetchSample1 flatMap {
    case Some(sample1) => fetchSample2(sample1) flatMap {
      case Some(sample2) =>
        compute(sample1, sample2) match {
          case Some(previousComputation) => anotherAsyncComputation(previousComputation) map (Option(_))
          case _ => Future.successful(None)
        }
    }
}

Alternatively with Scalaz OptionT monad transformer and some boilerplate you can keep the types compatible in a single for comprehension like so...

import scalaz._
import scalaz.OptionT._

def optionTImpl: Future[Option[Int]] = (for {
    sample1 <- optionT(fetchSample1)
    sample2 <- optionT(fetchSample2(sample1))
    previousComputation <- optionT(Future.successful(compute(sample1, sample2)))
    finalResult <- optionT(anotherAsyncComputation(previousComputation) map (Option(_)))
  } yield finalResult).run

Finally with The OptionTFutureUtils you can further simplify it to

import com.fortysevendeg.commons.scala.utils.OptionTFutureConversion._

def optionTFutureUtils : Future[Option[Int]] = (for {
    sample1 <- ? <~ fetchSample1
    sample2 <- ? <~ fetchSample2(sample1)
    previousComputation <- ? <~ compute(sample1, sample2)
    finalResult <- ? <~  anotherAsyncComputation(previousComputation)
  } yield finalResult).run

Note type wrapping to Future[Option] is no longer necessary as the conversions are automatically provided for many common objects such as Option, Future[A], A, etc...

This keeps for a nice and simpler operation chaining resulting in the final Future[Option[A]]

  • <* wraps any expression into an async Future(exp) then OptionT[Future, A]
  • <~ wraps any expression into its OptionT[Future, A]
  • ? is a an alias for optT

Install

Simply add the following dependency to your SBT based build

resolvers += "47deg Public" at "https://47degrees.bintray.com/snapshots"

libraryDependencies += "com.fortysevendeg" %% "scala-commons-47" % "0.1-SNAPSHOT" changing()

Credits

Scala Commons 47 is a library maintained by the 47 Degrees team.

Continuous Integration

CI and Artifact Repository hosted in ClinkerHQ.com

ClinkerHQ

License

Copyright (C) 2014 47 Degrees, LLC http://47deg.com hello@47deg.com

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.

About

An heterogeneous collection of Scala related utils, traits and classes


Languages

Language:Scala 100.0%