我可以使用更高种类的类型作为参数来创建类的单个实例吗?

问题描述 投票:0回答:1

要简洁但足够描述性地提出问题是很困难的。我想通过交集操作为

Semigroup
创建一个
Set
实例。因此,我试图与编译器沟通,我希望所有集合都有一个实例,无论其类型参数如何,但组合应该仅适用于相同元素类型的集合。

trait Semigroup[A] {
  def combine(x: A, y: A): A
}

object Semigroup {
  implicit def setIntersectionSG: Semigroup[Set[_]] = new Semigroup[Set[A]] { //error: not found: type A
    def combine(s1: Set[A], s2: Set[A]) = s1.intersect(s2)
  }
}

如果我尝试在整个半群定义中使用通配符类型参数,我会得到

type mismatch;
[error]  found   : Set[_$4] (in scala.collection.immutable)
[error]  required: Set[_$3] (in scala.collection)
[error]     def combine(s1: Set[_], s2: Set[_]) = s1.intersect(s2)
[error]                                                        ^

这在 Scala 2 或 3 中可行吗?如果是,怎么办?如果没有,为什么?

scala higher-kinded-types
1个回答
0
投票

有几种方法可以做到这一点,但没有一个使用存在类型(

Set[_]
):

  1. 隐式输入参数:
trait Semigroup[A] {
  def combine(x: A, y: A): A
}

object Semigroup {
  implicit def setIntersectionSG[A]: Semigroup[Set[A]] = new Semigroup[Set[A] {
    def combine(s1: Set[A], s2: Set[A]) = s1.intersect(s2)
  }
}
  1. 如果是猫的
    Semigroup
    ,那么还有
    SemigroupK
// If F[_] is used as a type parameter, then it's a type constructor instead
// of existential type, Scala 3 allows making a distinction clearer:
// F[_] (type constructor) vs F[?] (existential type)
trait SemigroupK[F[_]] {

  def combineK[A](x: F[A], y: F[A]): F[A]

  def algebra[A]: Semigroup[F[A]] = combineK(_, _) // Single Abstract Method
}

SemigroupK
对于像集合这样的类型很有用,它们是类型参数的,但无论我们应用哪种类型参数都可以组合。

© www.soinside.com 2019 - 2024. All rights reserved.