IT干货网

scala之`class A[_]` 有什么用

oomusou 2024年10月01日 编程设计 39 0

符号类型 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 to Int, 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 old class A.

new FlyingDog[A] { ... } 
// error: A takes no type parameters, expected: one 
// (aka 'kind mismatch') 

There are two solutions:

  1. Declare class A[_] instead. (Don't do that.)

  2. Use a type lambda:

    new FlyingDog[({ type λ[α] = A })#λ] 
    

or even

new FlyingDog[({ type λ[_] = A })#λ] 


评论关闭
IT干货网

微信公众号号:IT虾米 (左侧二维码扫一扫)欢迎添加!