符号类型 class A[_]
或 def a[_](x: Any)
有一个无法在正文中引用的类型参数,因此我看不到它的用处以及编译的原因。如果尝试引用此类型参数,则会引发错误:
scala> class A[_] { type X = _ }
<console>:1: error: unbound wildcard type
class A[_] { type X = _ }
^
scala> def a[_](x: Any) { type X = _ }
<console>:1: error: unbound wildcard type
def a[_](x: Any) { type X = _ }
^
有人能告诉我这种类型在 Scala 中是否有用例吗?确切地说,我不是指类型参数中的存在类型或更高种类的类型,仅指那些小
[_]
这构成了完整的类型参数列表。
请您参考如下方法:
因为我没有得到我期望的答案,我把这个带到scala-language .
我在这里粘贴了 Lars Hupel 的答案(因此,所有学分都适用于他),这主要解释了我想知道的内容:
I'm going to give it a stab here. I think the use of the feature gets clear when talking about type members.
Assume that you have to implement the following trait:
trait Function { type Out[In] def apply[In](x: In): Out[In] }
This would be a (generic) function where the return type depends on the input type. One example for an instance:
val someify = new Function { type Out[In] = Option[In] def apply[In](x: In) = Some(x) } someify(3) res0: Some[Int] = Some(3)
So far, so good. Now, how would you define a constant function?
val const0 = new Function { type Out[In] = Int def apply[In](x: In) = 0 } const0(3) res1: const0.Out[Int] = 0
(The type
const0.Out[Int]
is equivalent toInt
, but it isn't printed that way.)Note how the type parameter
In
isn't actually used. So, here's how you could write it with_
:val const0 = new Function { type Out[_] = Int def apply[In](x: In) = 0 }
Think of
_
in that case as a name for the type parameter which cannot actually be referred to. It's a for a function on the type level which doesn't care about the parameter, just like on value level:(_: Int) => 3 res4: Int => Int = <function1>
Except …
type Foo[_, _] = Int <console>:7: error: _ is already defined as type _ type Foo[_, _] = Int
Compare that with:
(_: Int, _: String) => 3 res6: (Int, String) => Int = <function2>
So, in conclusion:
type F[_] = ConstType // when you have to implement a type member def foo[_](...) // when you have to implement a generic method but don't // actually refer to the type parameter (occurs very rarely)
The main thing you mentioned,
class A[_]
, is completely symmetric to that, except that there's no real use case.Consider this:
trait FlyingDog[F[_]] { def swoosh[A, B](f: A => B, a: F[A]): F[B] }
Now assume you want to make an instance of
FlyingDog
for your plain oldclass A
.new FlyingDog[A] { ... } // error: A takes no type parameters, expected: one // (aka 'kind mismatch')
There are two solutions:
Declare
class A[_]
instead. (Don't do that.)Use a type lambda:
new FlyingDog[({ type λ[α] = A })#λ]
or even
new FlyingDog[({ type λ[_] = A })#λ]