What does "ap" of \/ in Scalaz do?

I am looking at disjunction type of scalaz and I noticed method ap

  /** Apply a function in the environment of the right of this disjunction. */
  def ap[AA >: A, C](f: => AA / (B => C)): (AA / C) =
    f flatMap (ff => map(ff(_)))

I guess I understand what it does. Now I wonder when and why one should actually use it ? Are there any examples of using this ap function ?


The disjunction you are looking for:

import scalaz.{ /, -/ /-, EitherT }
import scalaz.syntax.ToIdOps

object Testing extends ToIdOps // left and right methods come from there {
  // say you have the following method
  def someMethod(flag: Boolean): /[Exception, SomeObject] {
    if (flag) someObj.right else new Exception("this is a sample").left
  }
}

// pattern matching
val x = someMethod match {
  case /-(right) => // this is someObject
  case -/(err) => // deal with the error  
}

// catamorphism
def methodThatDealsWithObj(obj: someObject)
def methodThatDealsWithErr(err: Exception)
someMethod.fold(methodThatDealsWithObj)(methodThatDealsWithErr)

// for comprehensions
// ap behaves just like EitherT.
for {
  correctResponse <- EitherT(someMethod)
}

Update

To understand how EitherT and ap works, think of an Option , which has Some and None and potential matches. With an Option , you would do:

for {
  a <- someOption
} yield ..

With scalaz./ , you usually put an Exception on the left and a "correct" return type on the right. ap is a function that says apply this if the either has the correct type.

for {
  correctResponse <- ap(someEitherReturnMethod)
}

Use cases

The most common things I can think off where I use them avidly is complex asynchronous flows, such as OAuth1 or OAuth2, where I care about fine grained chaining of errors.

You can use / as the return of a Future :

def someComplexThirdPartyApiCall: Future[/[Exception, CorrectReturn]] = {
}

Because you can flatMap over futures, you can chain a couple methods like the above, collect and propagate errors.

Example

  def method1: Future[/[Exception, String]]
  def method2(result: String): Future[/[Exception, String]]

  def chainExample: Future[/[Exception, Int]] = {
    for {
      firstResult <- EitherT(method1)
      secondResult <- EitherT(method2(firstResult))
    } yield secondResult.toInt
  }
链接地址: http://www.djcxy.com/p/78266.html

上一篇: openCV AdaptiveThreshold与Otsu阈值。 投资回报率

下一篇: \ Scalaz中的“ap”是做什么的?