简体   繁体   English

Scala类型相等和路径依赖类型

[英]Scala type equality and path-dependent types

I am trying to express a constraint like: 我试图表达一个约束,如:

in a method def run[A, B](...), B must be equal to A#SomeInner

Here is my example code: 这是我的示例代码:

trait Wrapper {
  type Implementation
  implicit val instance: Data[Implementation]
}

trait Data[A] {
  def create : A
}

object DataInstances {
  implicit object IntData extends Data[Int] { def create = 0}
  implicit object StringData extends Data[String] { def create = "<empty>"}
  implicit object FloatData extends Data[Float] { def create = 0.5F}
}


import DataInstances._

object IntWrapper extends Wrapper { type Implementation = Int; implicit val instance = IntData }
object StringWrapper extends Wrapper { type Implementation = String; implicit val instance = StringData}
object FloatWrapper extends Wrapper { type Implementation = Float; implicit val instance = FloatData}



object Test extends App {

  def run[W <: Wrapper, D](wrapper: W)(implicit data: Data[D], ev: D =:= W#Implementation) : D = {
    data.create
  }

  run(StringWrapper)
}

and here I get a compilation error: 在这里,我得到一个编译错误:

Error:(31, 6) ambiguous implicit values:
              both object IntData in object DataInstances of type DataInstances.IntData.type
              and object StringData in object DataInstances of type DataInstances.StringData.type
              match expected type Data[D]
              run(StringWrapper)
                ^ 

Can you explain me why the compiler finds it ambiguous? 您能解释一下为什么编译器觉得模棱两可吗? From what I can tell (and what I tried to express) is that when I pass StringWrapper then, according to type equality evidence the only possible value for D would be String and therefore the only possible value for data would be StringData . 据我所知(以及我试图表达的)是,当我通过StringWrapper ,根据类型相等性证据, D的唯一可能值为String ,因此data唯一可能的值为StringData

But obviously the compiler doesn't think so :) 但显然编译器并不这么认为:)

And what would be the way to express this constraint properly? 正确表达此约束的方法是什么?

I don't see a reason to introduce type D in method run. 我看不出在方法运行中引入类型D的理由。 Without it method signature looks simpler and successfully compiles 没有它,方法签名看起来更简单并且可以成功编译

def run[W <: Wrapper](wrapper: W)(implicit data: Data[W#Implementation]) : W#Implementation = {
     data.create
}

+++ +++

btw, if you change order of implicits in your original method it will compile too, looks like 'ev' help to "type-bound" implicit resolution for data 顺便说一句,如果您在原始方法中更改隐式命令的顺序,它也将进行编译,看起来像是“ ev”帮助“类型绑定”数据的隐式解析

  def run[W <: Wrapper, D](wrapper: W)(implicit ev: D =:= W#Implementation, data: Data[D]) : D = {
    data.create
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM