堆叠意味着转换

时间:2016-10-26 20:59:56

标签: scala future functor

我正试图尽可能地利用期货。

这是我目前的测试代码:

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看到的那种灵感。

1 个答案:

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