如何在Scala中将依赖于路径的类型与类型类一起使用

steinybot

我在依赖路径的类型上遇到了一些问题。

我有一些Foo带有抽象类型成员的类型F诸如的实例Bar将提供具体类型。

然后是一个类型类Baz对于每种的具体类型,我都有类型类的实例Foo#F(但Foo本身没有)。

这是一个例子:

sealed trait Foo {
  type F
}

object Bar extends Foo {
  type F = Array[Byte]
}

trait Baz[B] {
  def b(b: B): String
}

object Baz {
  implicit val bazByteArray: Baz[Array[Byte]] = (b: Array[Byte]) => new String(b)
}

我无法编译它:

def f(a: Foo): Baz[a.F] = {
  val baz = a match {
    case bar@Bar => g(bar)
  }
  baz
} // Expression of type Baz[(a.type with Bar.type)#F] doesn't conform to Baz[a.F]

val x2: Foo = Bar
val y2: Baz[x2.F] = f(x2) // Expression of type Baz[Foo#F] doesn't conform to expected type Baz[x2.F]

这样可以编译:

def g(a: Foo)(implicit baz: Baz[a.F]): Baz[a.F] = {
  baz
}

val x1: Bar.type = Bar
val y1: Baz[x1.F] = f(x1)

为什么g编译却不编译f类型不一样吗?

我该如何f编译?我需要补充一些证据吗?

安德烈(Andrey Tyukin)

似乎有点类似于这个问题这是一种使其编译的方法:

sealed trait Foo {
  type F
  def asSingleton: FooSingleton[F]
}

trait FooSingleton[X] extends Foo {
  type F = X
  def asSingleton: FooSingleton[X] = this
}

object Bar extends FooSingleton[Array[Byte]]

trait Baz[B] {
  def b(b: B): String
}

object Baz {
  implicit val bazByteArray: Baz[Array[Byte]] = 
    (b: Array[Byte]) => new String(b)
}

def g(a: Foo)(implicit baz: Baz[a.F]): Baz[a.F] = {
  baz
}

val x1: Bar.type = Bar
val y1: Baz[x1.F] = f(x1)

def f[T](a: Foo { type F = T } ): Baz[T] = {
  (a.asSingleton: FooSingleton[T]) match {
    case bar @ Bar => g(bar)
  }
}

val x2: Foo = Bar
val y2: Baz[x2.F] = f(x2)

您进行g编译,因为baztype的依赖于路径的参数Baz[a.F]来自外部,因此编译器会插入一个具体的隐式实例,并且a内部的任何地方都不会使用实际值g

f不会编译,因为只会B[a.F]出现在返回类型中,并且在将实际参数传递给之前无法使其更加具体af

从某种意义上说,f中断会破坏参数a和返回值之间的路径,因为它会导致以下“不连续跳转”:

  • 从...开始 a: Foo
  • 从跳转aBar单(通过模式匹配)
  • 用于g从混凝土Bar单例到混凝土Baz[Array[Byte]]
  • 尝试将其返回Baz[Array[Byte]],似乎不再与之相关Baz[a.F]

可以通过证明不连续的“跳转”确实只是一条始终保持在同一位置的标识路径来修复此路径,因此它实际上不会在任何地方移动,因此a.F和推断的类型相同,即T

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如何在assertThat中将hamcrest nullValue与类型推断一起使用

泛型类型如何在Scala中与继承一起使用?

如何在JPA / Hibernate中将@Id与字符串类型一起使用?

从依赖于路径的类型混合中访问值

如何将RelativeLayout与依赖于控件自身位置的控件一起使用?

类型别名如何使用来指定依赖于模板参数的模板模板参数?

使用依赖于上下文绑定的选择编写类型类

使用依赖于lambda函数的类型作为返回类型

Scala类型投影:在依赖于路径的特征中拾取对象

如何在PostgreSQL中将tsvector_update_trigger与数组类型一起使用?

如何在类型依赖于派生类的基础模板类中声明成员?

朱莉娅:如何正确定义使用依赖于数字的类型的函数?

依赖于特定类类型的C ++模板方法?

如何在Python中将C函数与复杂类型一起使用?

如何在Scala的类型类中使用依赖类型?

如何在Haskell中将fold函数与其他数据类型一起使用

如何在Scala类型类中将帮助程序类型定义为与路径无关?

如何使类型类与Scala中的异构列表一起使用

如何在飞行中将BLOB数据类型与不同的数据库一起使用?

如何在实体框架中将过程与用户定义的表类型一起使用

使用'type'关键字和依赖于路径的类型覆盖类型

正确指定依赖于路径的类型注释

C ++变量在类的所有实例中使用依赖于类的类型和函数具有相同的值

在Scala中将抽象类型与类型类一起使用

如何使用@InjectMocks依赖于另一个要模拟的类?

Scala:在隐式参数中抽象依赖于路径的类型

MATLAB:如何将 fsolve 与多个输入一起使用,每个输入都依赖于多个参数?

在 Scala 中将类型 lambda 与更高级的类型一起使用:如何让编译器正确推断类型?

如何在 Kotlin/Arrow 中调用依赖于多个类型类的多态函数