1

単純なカスタム文字列インターポレーターを作成しようとしていますが、型パラメーターを使用しない限り成功します。

import scala.concurrent.Future

object StringImplicits {
  implicit class FailureStringContext (val sc : StringContext) extends AnyVal {

    // This WORKS, but it's specific to Future :(  

    def fail[T](args : Any*): Future[T] = {
      val orig = sc.s (args : _*)
      Future.exception[T](new Exception(orig))
    }

    // I want this to work for Option,Try,Future!!

    def fail[M,T](args:Any*): M[T] = {
      val orig = sc.s (args : _*)

      // Obviously does not work.. 
      M match {
        case Future => Future.exception(new Exception(orig))
        case Option => None
        case Try => Failure(new Exception(orig))
        case  _ => ???
      }
    }
  }
}

これを機能させることはできますか?私はこれら 3 つのタイプを定義していないため、パラメトリック ポリモーフィズムを使用できません。

その疑似コード パターン マッチの型レベルで同等のものは何ですか?

最新の試み

私の最近の試みは暗黙的に使用することでしたが、そのような暗黙的なものはありません! 型推論に従って、コンパイラが返してほしい型を取得することに実際に興味があります。

def fail[T, M[T]](args:Any*): M[T] = {
  val orig = sc.s(args: _*)

  implicitly[M[T]] match {
    case _:Future[T] => Future.exception(new Exception(orig))
    case _ => ???
  }
}


<console>:18: error: could not find implicit value for parameter e: M[T]
             implicitly[M[T]] match {
                       ^
<console>:19: error: value exception is not a member of object scala.concurrent.Future
               case _: Future[T] => Future.exception(new Exception(orig))
                                           ^
4

1 に答える 1

1

私の意見では、最も簡単なのは古き良きオーバーロードに依存することです。処理したい型ごとに異なるオーバーロードを定義するだけです。

もちろん、同じシグネチャで異なるオーバーロードが存在するという問題があり、scala ではいつものように、トリックを使用してそれらを回避できます。ここでは、ダミーの暗黙的なパラメーターを追加して、各オーバーロードに個別の署名を強制します。きれいではありませんが、機能し、この場合は十分です。

import scala.concurrent.Future
import scala.util.{Try, Failure}

implicit class FailureStringContext (val sc : StringContext) extends AnyVal {

  def fail[T](args : Any*): Future[T] = {
    Future.failed[T](new Exception(sc.s (args : _*)))
  }

  def fail[T](args : Any*)(implicit dummy: DummyImplicit): Option[T] = {
    Option.empty[T]
  }

  def fail[T](args : Any*)(implicit dummy: DummyImplicit, dummy2: DummyImplicit): Try[T] = {
    Failure[T](new Exception(sc.s (args : _*)))
  }
}

そして多田:

scala> fail"oops": Option[String]
res6: Option[String] = None

scala> fail"oops": Future[String]
res7: scala.concurrent.Future[String] = scala.concurrent.impl.Promise$KeptPromise@6fc1a8f6

scala> fail"oops": Try[String]
res8: scala.util.Try[String] = Failure(java.lang.Exception: oops)
于 2016-07-07T11:43:02.427 に答える