【发布时间】:2014-03-20 19:08:09
【问题描述】:
我正在查看disjunction scalaz 类型,我注意到方法ap
我想我明白它的作用。现在我想知道何时以及为什么应该实际使用它?有没有使用这个ap函数的例子?
【问题讨论】:
我正在查看disjunction scalaz 类型,我注意到方法ap
我想我明白它的作用。现在我想知道何时以及为什么应该实际使用它?有没有使用这个ap函数的例子?
【问题讨论】:
你正在寻找的析取:
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)
}
更新
要了解EitherT 和ap 的工作原理,请考虑Option,它具有Some 和None 以及潜在的匹配项。使用Option,您可以:
for {
a <- someOption
} yield ..
对于scalaz.\/,您通常将Exception 放在左侧,将“正确”返回类型放在右侧。 ap 是一个函数,如果其中一个具有正确的类型,则应用此函数。
for {
correctResponse <- ap(someEitherReturnMethod)
}
用例
我能想到的最常见的事情是我热衷于使用它们的地方是复杂的异步流,例如 OAuth1 或 OAuth2,我关心的是细粒度的错误链接。
您可以使用\/ 作为Future 的返回:
def someComplexThirdPartyApiCall: Future[\/[Exception, CorrectReturn]] = {
}
因为你可以flatMap over futures,你可以像上面那样链接几个方法,收集和传播错误。
示例
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
}
【讨论】:
ap behaves just like EitherT吗?为什么要首先使用EitherT?
f1: A => Future[\/[Exception, B] 和f2: B => Future[\/[Exception, C]] 我怎么能用\/.ap 组合它们来获得f3:A => Future[\/[Exception, C]?
map 和flatMap。
f1 和f2 组合成f3(如上面评论中定义的那些函数)?