辅助模式用法在不推断适当类型的情况下编译 [英] Aux-pattern usage compiles without inferring an appropriate type

查看:52
本文介绍了辅助模式用法在不推断适当类型的情况下编译的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Consider the following simple example involving 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 会编译.我也预计类型不匹配.

I don't really understand why testBaz compiles. I expected type mismatch as well.

推荐答案

似乎没有深层原因.

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

Since when you specify type parameter explicitly both methods compile

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 只是没有推断出来

in the first case the type baz.foo.T is inferred while in the second case the type foo.T is just not inferred

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

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

In Scala it's always possible that some type parameter will not be inferred and you'll have to specify it explicitly.

也许我找到了可能的原因.

Maybe I found a possible reason.

代码

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

不编译,但如果你使 foo 成为 val

doesn't compile but if you make foo a val

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

然后就可以了.可能问题是当 fooval 时,它更稳定".在这种情况下,它更容易"推断路径依赖类型 foo.T.

then it does. Probably the thing is that when foo is a val it's more "stable" and in such case it's "easier" to infer path-dependent type foo.T.

所以 testBaztestFoo 的区别在于 Baz 是一个 case 类,所以 foo 是一个val 而在 testFoofoo 只是一个方法参数,因此不太稳定".

So the difference between testBaz and testFoo can be that Baz is a case class so foo is a val while in testFoo foo is just a method parameter and therefore less "stable".

同理,相反

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

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

doesn't compile but if we extract a variable

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

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

then it does. The thing is that now a is stable and type a.T can be inferred.

这篇关于辅助模式用法在不推断适当类型的情况下编译的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆