首页 > 解决方案 > 导入不会在范围内带来隐含

问题描述

implicit在范围内面临一个关于 unreachable 的错误:

Error:(38, 68) could not find implicit value for parameter strategy: XXX.NeoStrategy[T] (summoner: Summoner, v: String) => summoner.summonEvaluation[T](v)

我实现了蒂姆对该问题的回答:https ://stackoverflow.com/a/56668734/3896166

我试图implicit object在范围内导入策略TypeTable

  import XXX.NeoStrategies._

但没有成功。

以下是我要使用的基本逻辑的每个文件:

  object TypeLib {
    sealed trait Type_top
    trait Type_A extends Type_top
    trait Type_B extends Type_top
  }
  trait NeoStrategy[T <: Type_top] {
    def evaluate(v: String, helper: Helper): Int
  }

  object NeoStrategies {
    implicit object NeoStrategy_A extends NeoStrategy[Type_A] {
      def evaluate(v: String, helper: Helper): Int = 1
    }
    implicit object NeoStrategy_B extends NeoStrategy[Type_B] {
      def evaluate(v: String, helper: Helper): Int = 2
    }
  }
  case class Helper(name: String) {
    def summonEvaluation[T <: Type_top](v: String)(implicit strategy: NeoStrategy[T]): Int = {
      strategy.evaluate(v, this)
    }
  }
  trait TypeOMap {
    protected def computeStuff[T <: Type_top]: (Helper, String) => Int
    protected val computeMap: Map[String, (Helper, String) => Int]
  }
  import XXX.NeoStrategies._

  trait TypeTable extends TypeOMap {
    override protected def computeStuff[T <: Type_top]: (Helper, String) => Int = {
      (helper: Helper, v: String) => helper.summonEvaluation[T](v)
    }
    override protected val computeMap = Map(
      "a" -> computeStuff[Type_A],
      "b" -> computeStuff[Type_B]
    )
  }
class Summoner extends TypeTable {

  def callsMapAndEvaluates(typeIdentifier: String, helper: Helper, param: String): Double = {

    computeMap(typeIdentifier)(helper, param)
  }
}
object StackO {

  def main(args: Array[String]): Unit = {

    val mySummoner = new Summoner

    // mySummoner allows the selecting of a given type with
    // its "typeIdentifier" input in combination with the "TypeTable" it extends
    val r = mySummoner.callsMapAndEvaluates("a", Helper("make it right"), "I, parameter")
  }
}

这不是我第一次使用implicits 但不是像computeMap上面这样的东西。不过,我理解它的逻辑,但未能使其正确。

我怎样才能summoner.summonEvaluation[T](v)找到所需的implicit

标签: scalaimplicit

解决方案


只需添加上下文绑定

override protected def computeStuff[T <: Type_top : NeoStrategy] ...

看来您想使用单例类型。在 Scala 2.12 + 无形中

  import shapeless.Witness

  object TypeLib {
    sealed trait Type_top
    trait Type_A extends Type_top
    trait Type_B extends Type_top
  }

  import TypeLib._

  trait NeoStrategy[S <: String] {
    type T <: Type_top
    def evaluate(v: S, summoner: Summoner): Int
  }

  object NeoStrategy {
    type Aux[S <: String, T0 <: Type_top] = NeoStrategy[S] { type T = T0 }
    def mkStrategy[S <: String, T0 <: Type_top](f: (S, Summoner) => Int): Aux[S, T0] = new NeoStrategy[S] {
      override type T = T0
      override def evaluate(v: S, summoner: Summoner): Int = f(v, summoner)
    }

    implicit val NeoStrategy_A: NeoStrategy.Aux[Witness.`"a"`.T, Type_A] = mkStrategy((_, _) => 1)
    implicit val NeoStrategy_B: NeoStrategy.Aux[Witness.`"b"`.T, Type_B] = mkStrategy((_, _) => 2)
  }

  case class Summoner(name: String) {
    def summonEvaluation[S <: String](s: Witness.Aux[S])(implicit
      strategy: NeoStrategy[S]): Int = {
      strategy.evaluate(s.value, this)
    }
  }

  def main(args: Array[String]): Unit = {

    val mySummoner = Summoner("stack question")

    val r = mySummoner.summonEvaluation("a")
    val r1 = mySummoner.summonEvaluation("b")

    println(r) // 1
    println(r1) // 2
  }

在 Scala 2.13 中

  object TypeLib {
    sealed trait Type_top
    trait Type_A extends Type_top
    trait Type_B extends Type_top
  }

  import TypeLib._

  trait NeoStrategy[S <: String with Singleton] {
    type T <: Type_top
    def evaluate(v: S, summoner: Summoner): Int
  }

  object NeoStrategy {
    type Aux[S <: String with Singleton, T0 <: Type_top] = NeoStrategy[S] { type T = T0 }
    def mkStrategy[S <: String with Singleton, T0 <: Type_top](f: (S, Summoner) => Int): Aux[S, T0] = new NeoStrategy[S] {
      override type T = T0
      override def evaluate(v: S, summoner: Summoner): Int = f(v, summoner)
    }

    implicit val NeoStrategy_A: NeoStrategy.Aux["a", Type_A] = mkStrategy((_, _) => 1)
    implicit val NeoStrategy_B: NeoStrategy.Aux["b", Type_B] = mkStrategy((_, _) => 2)
  }

  case class Summoner(name: String) {
    def summonEvaluation[S <: String with Singleton](s: S)(implicit
      value: ValueOf[S],
      strategy: NeoStrategy[S]): Int = {
      strategy.evaluate(s, this)
    }
  }

  def main(args: Array[String]): Unit = {

    val mySummoner = Summoner("stack question")

    val r = mySummoner.summonEvaluation("a")
    val r1 = mySummoner.summonEvaluation("b")

    println(r) // 1
    println(r1) // 2
  }

推荐阅读