Scala隐式def返回带有B的A

时间:2019-02-21 04:29:45

标签: scala generics typeclass implicit dotty

我一直对此不敢恭维,我不知道是否有办法正确地做到这一点。 我觉得我知道问题出在哪里,但不知道如何解决。

我有一个方法:

implicit def combineAlg[A: Alg, B: Alg]: Alg[A with B] = ...

如果我明确地调用它,它可以正常工作,但是永远不会得到正确的暗示。

// works
implicit val comb: Alg[A with B] = combineAlg[A, B]

// doesn't work
implicit val comb: Alg[A with B] = implicitly[Alg[A with B]]

通过-Xlog-implicits的调试,我相信它的调用是combineAlg[A with B, Nothing]

我正在寻找一种方法来做类似的事情:

implicit def combineExpAlg[AB, A >: AB, B >: AB]

implicit def combineExpAlg[AB, A, B](implicit ev1: AB <:< A, ev2: AB <:< B)

,以便它了解需要将“ with”分开,但两者均无济于事。

不确定是否有办法做到这一点,实际上是我在Scala中为“对象代数”所做的实验,我正在尝试查看如何删除样板。

如果有解决方案,那就太好了。 一个简单的解决方案也是可以接受的,因为我也在那里实现它,以查看某些新功能是否使它更简单。

如果需要更多信息,您可以查看存储库here 我要更改的是algebra.combineExpAlg。 之所以会这样,是因为我在algebra.interpreters.package中定义了特定的隐式函数,这些隐式函数专门拼出了每个解释器对,这就是我要概括的内容。

1 个答案:

答案 0 :(得分:1)

以下代码编译:

  trait Alg[T]

  trait LowPriorityAlg {
    implicit def bAlg: Alg[B0] =  ???
  }
  object Alg extends LowPriorityAlg {
    implicit def aAlg: Alg[A0] =  ???
    implicit def combineAlg[AB, A: Alg, B: Alg](implicit ev1: AB <:< A, ev2: AB <:< B): Alg[AB] = ???    
  }

  trait A0
  trait B0

  val comb: Alg[A0 with B0] = Alg.combineAlg[A0 with B0, A0, B0]

  val comb1: Alg[A0 with B0] = implicitly[Alg[A0 with B0]]