2016-10-26 10 views
0

私は可能な限り軽量の先物を使用しようとしています。変換を積み重ねることを意味する

は、ここに私の現在のテストコードです:

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 
    */ 
} 

抽出しextracted2が働いているが、各唯一私が定義した2つの暗黙的な変換のいずれかを使用しています。

extracted3は、明示的にプラスおよびcst1をFuture [X]値に持ち込み、a <*> bap(a,b)に変換することを目指しています。しかし、コンパイラは私に同意していないようです。

私は可能なことを達成しようとしていますか?もしそうなら、私はそれを動作させるために何を変えなければならないのですか?

PS:これは私は一種の私はHaskellのを使用して見てきたものからインスピレーションを得ました。

+0

'cst'は未定義ですか? – tkachuko

+0

いいえ、2回の暗黙的な変換を同時に行うことはできません。 – flavian

答えて

3

私は、あなたが「一度に」ルールに対してアップぶつけていると思います。 Programming in Scalaから

、(第1版):

1つずつルール:一つだけの暗黙のが試されます。コンパイラは x + yをconvert1(convert2(x))+ yに書き直すことはありません。そうすること が誤ったコードを劇的に向上させるために時間をコンパイルし、それが プログラマが書き、何 プログラムが実際に何をするかの違いを増加させる原因となります。正直言って、コンパイラは、すでに中間にあるときに暗黙的な変換を挿入しません。 別の暗黙的な変換を試みます。


は@tkachukoを指摘したように、可能性の暗黙のパラメータを使用してこの制限の回避策がある、しかし、1つの単純な解決策は、二つの部分に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) 
} 
+0

しかし、暗黙のdef chainingでターゲットを達成できるように見えます:http://docs.scala-lang.org/tutorials/FAQ/chaining-implicits.html – tkachuko

関連する問題