scala - Aux-pattern 用法在不推断适当类型的情况下进行编译

标签 scala types type-inference type-safety existential-type

考虑以下涉及 Aux-pattern 的简单示例:

sealed trait AdtBase

abstract case class Foo(){
  type T <: AdtBase
}

object Foo{
  type Aux[TT] = Foo { type T = TT }
}

abstract case class Bar(){
  type T <: AdtBase
  val foo: Foo.Aux[T]
}

object Bar {
  type Aux[TT] = Bar { type T = TT }

  def apply[TT <: AdtBase](f: Foo.Aux[TT]): Bar = new Bar() {
    override type T = TT
    override val foo: Foo.Aux[T] = f
  }
}

case class Baz(foo: Foo)

def testBaz(baz: Baz) = Bar(baz.foo) //Compiles fine
def testFoo(foo: Foo) = Bar(foo) //Error: Type mismatch

Scastie

我真的不明白为什么 testBaz 可以编译。我也预计类型不匹配。

最佳答案

似乎没有深层原因。

因为当您显式指定类型参数时,两种方法都会编译

def testBaz(baz: Baz) = Bar[baz.foo.T](baz.foo) //compiles
def testFoo(foo: Foo) = Bar[foo.T](foo)         //compiles

似乎在

def testBaz(baz: Baz) = Bar(baz.foo) //compiles
//def testFoo(foo: Foo) = Bar(foo)   //doesn't compile

在第一种情况下,类型 baz.foo.T 被推断出来,而在第二种情况下,类型 foo.T 只是没有被推断出来

// found   : Foo
// required: Foo.Aux[this.T]

在 Scala 中,总是有可能无法推断出某些类型参数,您必须明确指定它。


也许我找到了一个可能的原因。

代码

class testFoo2(foo: Foo) {
  // Bar(foo) // doesn't compile
}

不编译,但如果你将 foo 设为 val

class testFoo2(val foo: Foo) {
  Bar(foo) // compiles
}

然后就可以了。可能是当 foo 是一个 val 时它更“稳定”,在这种情况下它更“容易”推断路径相关类型 foo.T.

所以 testBaztestFoo 之间的区别可能是 Baz 是一个案例类,所以 foo 是一个val 而在 testFoofoo 只是一个方法参数,因此不太“稳定”。

同样,相反

trait A[T]
def m[T](a: A[T]) = ???
m(??? : A[_]) // compiles

代码

trait A { type T } 
def m[_T](a: A { type T = _T}) = ??? 
m(??? : A) // doesn't compile

不编译但是如果我们提取一个变量

val a: A = ???
m(a) // compiles

然后就可以了。问题是现在 a 是稳定的并且可以推断类型 a.T

关于scala - Aux-pattern 用法在不推断适当类型的情况下进行编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64672950/

相关文章:

typescript - 如何通过函数签名从其他键的类型推断键的类型?

c# - 为什么 C# 不推断我的泛型类型?

generics - Scala 泛型和控制台自动完成

user-interface - 提示,像素和点,我的天哪!

c++ - 为什么 C++ 流使用 char 而不是 unsigned char?

generics - 如何包装nom tag_no_case解析器?

scala - toList 和 toBuffer 之间的类型推断不一致

scala - 获取脚本文件名并打印它

scala - 调用 super 构造函数

scala - 玩! scala 和 Akka : how to test if an actor A sent a message to an actor B?