\ / Scalaz中的“ap”有什么作用?

时间:2014-03-18 15:08:39

标签: scala scalaz

我正在查看disjunction类型的scalaz,我注意到方法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(_)))

我想我明白它的作用。现在我想知道何时以及为什么要实际使用它?是否有使用此ap函数的示例?

1 个答案:

答案 0 :(得分:4)

您正在寻找的分离:

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)
}

<强>更新

要了解EitherTap的工作原理,请考虑Option,其中包含SomeNone以及潜在的匹配项。使用Option,您可以:

for {
  a <- someOption
} yield ..

使用scalaz.\/时,您通常会在左侧放置一个Exception,并且#34;正确&#34;返回类型在右侧。 ap是一个函数,如果要么具有正确的类型,则应用此函数。

for {
  correctResponse <- ap(someEitherReturnMethod)
}

使用案例

我能想到的最常见的事情就是复杂的异步流程,例如OAuth1或OAuth2,我关心错误的细粒度链接。

您可以使用\/作为Future的回复:

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

因为你可以flatMap超过期货,你可以链接上面的几个方法,收集和传播错误。

示例

  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
  }