我正试图尽可能地利用期货。
这是我目前的测试代码:
import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.Future
import scala.util.Failure
import scala.util.Success
object Test1 extends App {
def lift[A](a: A): Future[A] = Future { a }
def ap[A, B](fct: Future[A => B], param: Future[A]): Future[B] =
for {
c <- param
o <- fct
} yield (o(c))
implicit def valToFuture[A](elem: A): Future[A] = lift(elem)
implicit class FutureInfix[A, B](val x: Future[A => B]) extends AnyVal {
def <*>(that: Future[A]) = ap(this.x, that)
}
val plus1: Int => Int = (x: Int) => x + 1
val cst1: Int = 1
val extracted: Future[Int] = ap(plus1, cst1)
val extracted2: Future[Int] = lift(plus1) <*> lift(cst1)
val extracted3: Future[Int] = plus1 <*> cst
/*
* - value <*> is not a member of Int ⇒ Int
* - not found: value cst
*/
}
extract和extracted2正在工作,但每个都只使用我定义的两个隐式转换中的一个。
extract3是我的目标,隐含地将plus和cst1提升为Future [X]值并将a <*> b
转换为ap(a,b)
。但编译器似乎不同意我的看法。
我正在努力实现的目标是什么?如果是这样,我需要做些什么才能使其有效?
PS:这是我从使用haskell看到的那种灵感。答案 0 :(得分:3)
我认为你一次碰到&#34;一次&#34;规则。
来自Programming in Scala,(第1版):
一次一个规则:只尝试了一个隐式规则。编译器会 永远不会将x + y重写为convert1(convert2(x))+ y。这样做会导致 编译时间会因错误的代码而急剧增加,而且会 增加程序员写的东西和什么之间的差异 该计划实际上。为了理智,编译器没有 当它已经在中间时插入进一步的隐式转换 尝试另一种暗示。
正如@tkachuko指出的那样,使用隐式参数可能会解决这个限制,但一个简单的解决方案是将FutureInfix
分成两部分。
implicit class FromFutureInfix[A, B](x: Future[A => B]) {
def <*>(that: Future[A]) = ap(x, that)
}
implicit class ToFutureInfix[A, B](x: A => B) {
def <*>(that: A) = ap(x, that)
}