【问题标题】:Mapping over a list of existential types映射存在类型列表
【发布时间】:2018-09-15 20:03:17
【问题描述】:

我有一个我想要映射的存在类型对象的列表。像这样的:

sealed abstract class IntBox(val v: Int)
case object IB1 extends IntBox(1)
case object IB2 extends IntBox(2)

case class Adder[A  <: IntBox](ib: A, v: Int) {
  def add(i: A) = v + i.v
}

val adders: List[Adder[_ <: IntBox]] = List(Adder(IB1, 0), Adder(IB2, 0))

adders.map(adder => adder.add(adder.ib))

但是,我遇到了类似的错误

found: adder.ib.type
required: _$1

我觉得这有点像因为map 以某种方式将不同的IntBoxs 统一为一种无法获得的匿名类型...

我可以在不强制转换的情况下得到我想要的吗(即adder.asInstanceOf[Adder[adder.ib.type]]...

【问题讨论】:

  • 那是什么 Scala 版本? Scastie 和我的本地 scala 安装在它们接近列表之前很久就给出了“特征或对象可能没有参数”。
  • 哈哈,抱歉我的意思是抽象类
  • 顺便说一句,事实证明这实际上是重复的(或至少非常接近重复),并且解决方案实际上是相同的:Q: Type inference with existential type

标签: scala types polymorphism existential-type


【解决方案1】:

类型不是不可获取的,可以通过类型模式匹配获取:

adders.map{ case a: Adder[t] => a.add(a.ib) }

这里,存在类型参数绑定到类型变量t,编译器可以正确推断出t的附加属性,而它无法推断出整个列表。

有关详细信息,请参阅8.3.1 of the Specification 部分。


trait 替换为class 的完整代码使其编译

sealed abstract class IntBox(val v: Int)
case object IB1 extends IntBox(1)
case object IB2 extends IntBox(2)

case class Adder[A  <: IntBox](ib: A, v: Int) {
  def add(i: A) = v + i.v
}

val adders: List[Adder[_ <: IntBox]] = List(Adder(IB1, 0), Adder(IB2, 0))

adders.map{ case a: Adder[t] => a.add(a.ib) }

【讨论】:

  • 这需要更多解释,因为它与 case a =&gt; 一样有效。无论发生什么都不涉及显式类型模式。
  • @JoePallas 这是一个有趣的观察!老实说:我不知道为什么会这样。我假设无论发生什么,它仍然涉及模式匹配。到目前为止,打印部分编译的代码并没有那么有启发性。你有清楚的解释为什么它适用于case a =&gt; ...,但不适用于a =&gt; ...,或者这条评论对我来说是额外的功课吗? ;) 我认为这本身就是一个很好的问题。你想问和/或回答这个问题吗?还是我应该问它并尝试自己回答?
  • @AndreyTyukin 我不打算布置作业,但我不知道其中的区别。我只是偶然发现了它,因为我很好奇为什么匹配一个未使用的类型变量很重要。这肯定远远超出了我的理解范围。
  • @JoePallas 我决定把它写成separate question,然后自己回答(显然,这是明确的encouraged)。我希望它能解释这个答案“哭泣”的更多细节。
猜你喜欢
  • 2021-10-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-17
  • 1970-01-01
  • 1970-01-01
  • 2021-07-15
  • 1970-01-01
相关资源
最近更新 更多