【问题标题】:scala type classes implicit ambiguityscala 类型类隐含歧义
【发布时间】:2017-06-05 02:06:02
【问题描述】:

在代数类型层次结构中设置类型类时遇到问题。

我有以下特点:

trait Field[F]{...}

trait VectorSpace3[V,F] extends Field[F]{...}

知道我想提供实现:

trait DoubleIsField extends Field[Double]{
   ...
}

trait DoubleTurple3IsVectorSpace3 extends VectorSpace3[(Double,Double,Double), Double] with Field[Double]{
   ...
}
trait MyOtherClassIsVectorSpace3 extends VectorSpace3[MyOtherClass, Double] with Field[Double]{
   ...
} 

//now the implicits
implicit object DoubleIsField extends DoubleIsField  
implicit object DoubleTurple3IsVectorSpace3 extends DoubleTurple3IsVectorSpace3 with DoubleIsField
implicit object MyOtherClassIsVectorSpace3 extends MyOtherClassIsVectorSpace3 with DoubleIsField 

最后两个隐式导致歧义:DoubleIsField 是 3 个隐式值的一部分,代码无法编译。在 scala 中如何处理这个问题?

编辑:

错误:

ambiguous implicit values:
[error]  both object DoubleIsField in object TypeClasses of type 
Russoul.lib.common.TypeClasses.DoubleIsField.type
[error]  and object DoubleTurple3IsVectorSpace3 in object TypeClasses of type 
Russoul.lib.common.TypeClasses.DoubleTurple3IsVectorSpace3.type
[error]  match expected type Russoul.lib.common.TypeClasses.Field[...Double]

EDIT2:

 def func()(implicit env: Field[Double]): Unit ={

 }

 func()

完整的测试程序:

object Test extends App {

trait Field[F]{

}

trait VectorSpace3[V,F] extends Field[F]{

}
trait DoubleIsField extends Field[Double]{

}

trait DoubleTurple3IsVectorSpace3 extends VectorSpace3[(Double,Double,Double), Double] with Field[Double]{

}


//now the implicits
implicit object DoubleIsField extends DoubleIsField
implicit object DoubleTurple3IsVectorSpace3 extends DoubleTurple3IsVectorSpace3 with DoubleIsField


def func()(implicit env: Field[Double]): Unit ={

}

func()

}

【问题讨论】:

  • DoubleIsField(第一个声明,不是object)未声明为traitclass。什么是编译器错误信息?
  • @MikeAllen 对不起,这是特质。它不是真正的代码。我只是写了简化版本来显示问题
  • @MikeAllen 查看编辑错误
  • 您的代码中是否有 implicit 函数参数?如果是这样,你能告诉我们它们的样子吗?
  • @MikeAllen 查看新编辑

标签: scala polymorphism typeclass implicit


【解决方案1】:

(根据您最近的评论更新...)

问题在于以下函数的定义:

def func()(implicit env: Field[Double]): Unit = {
  // ...
}

您的问题是您在同一范围内有多个此类型的 implicit 值,因此编译器无法知道要提供哪一个(它们都是可以表示为具有 Field[Double] 类型的隐式值) .

关于implicit 参数值的全部意义在于编译器可以识别一个值;如果它不能识别一个,它就无法读懂你的想法并选择正确的一个,你也不希望它随机选择一个。

您可用的选项如下:

  • 放弃使用 implicit 参数值并将值显式传递给您的函数。
  • 将带有implicit 参数的函数定义更改为具有唯一implicit 值的类型。
  • 使用单个implicit object 定义。 (很抱歉最初将其从列表中删除。)

【讨论】:

  • 当然,我必须将这些隐式移动到不同的范围...谢谢。一个额外的小问题:假设我有一个函数:
  • def func()(implicit composed: Field[...] with ExtraOperation[...]){...} 我对 Field 和 ExtraOperation 都有单独的隐式。有没有比使用 ExtraOperation 创建一个包含 Field 的额外对象更好的方法来提供 mixin ?
  • @Russoul 鉴于该声明,implicit 类型,例如,Field[X] 将不会与 implicit 类型的 implicit 参数匹配,如果它没有混入后者类型。我认为您可能过度使用 implicit 参数。你想做什么?
  • 我正在编写一个用于基本代数计算的简单库。我使用这些结构来构建库:@immutable case class ComplexOverField[A](real: A, imaginary:A)(implicit ev: Field[A] with Euclidean[A])
  • 顺便说一句,使用implicit 参数的替代方法是使用部分应用函数。例如,假设您有def greet(greeting: String, name: String) = s"$greeting $name"。你可以有val hi = greeting("Hi", _:String)。所以hi("Fred")greet("Hi", "Fred") 相同。这对你有用吗?
猜你喜欢
  • 1970-01-01
  • 2016-08-03
  • 2020-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-21
  • 2018-08-27
  • 1970-01-01
相关资源
最近更新 更多