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

Mic*_*ael 7 scala scalaz

我正在研究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功能的例子?

fla*_*ian 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)
}
Run Code Online (Sandbox Code Playgroud)

更新

要了解EitherT和 的ap工作原理,请考虑Option,它具有SomeNone以及潜在的匹配项。使用Option,你会这样做:

for {
  a <- someOption
} yield ..
Run Code Online (Sandbox Code Playgroud)

使用 时scalaz.\/,您通常会Exception在左侧放置一个“正确”的返回类型,在右侧放置一个“正确”的返回类型。ap是一个函数,表示如果其中一个具有正确的类型,则应用此函数。

for {
  correctResponse <- ap(someEitherReturnMethod)
}
Run Code Online (Sandbox Code Playgroud)

用例

我能想到的最常见的事情是我热衷于使用它们的地方是复杂的异步流程,例如 OAuth1 或 OAuth2,我关心的是细粒度的错误链接。

您可以用作\/a 的返回Future

def someComplexThirdPartyApiCall: Future[\/[Exception, CorrectReturn]] = {
}
Run Code Online (Sandbox Code Playgroud)

因为您可以flatMap通过 future,所以您可以链接上面的几个方法,收集和传播错误。

例子

  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
  }
Run Code Online (Sandbox Code Playgroud)