【问题标题】:Is there a shorthand for type variable 'm forSome { type m[O] <: UpperBound[O] }` in Scala?在 Scala 中是否有类型变量 'm forSome { type m[O] <: UpperBound[O] }` 的简写?
【发布时间】:2020-07-17 08:26:25
【问题描述】:

问题:

trait UpperBound[O]
trait High[F[O] <: UpperBound[O]]

def canEqual(that :Any) = that.isInstanceOf[High[_]]

def high(h :High[_]) = ???

不编译,因为 scalac 看到的是 _ 类型,而不是它期望的类型构造函数。如何解决它,最好不要写小说?

原始问题(在编辑回复 Dmytro 的答案之前)有:

def canEqual(that :Any) = that.isInstanceOf[High[m forSome { type m[O] <: UpperBound[O] }]]

def high(h :High[m forSome { type m[O] <: UpperBound[O] }] = ???

有没有通过使用通配符表达式来编写上述两种方法的更短的方法? 简单地在High 的类型参数位置使用_ 是行不通的,因为类型不匹配,_[_] 甚至不是有效的类型表达式。

【问题讨论】:

  • 关于你更新的问题,你的意思是def high(h: High[F] forSome {type F[O] &lt;: UpperBound[O] }) = ???吗?
  • 有趣。我从来不知道我在原始问题中写的内容与您在此处的 sn-p 之间存在差异。我需要更仔细地重新阅读 SLS,因为我根本看不到它来自哪里。
  • 好吧,我想很明显List[X[A]] forSome { type A }List[X[A] forSome { type A }] 是不同的。前者由具有X[A] 类型的元素组成,其中A 是任意的,但对于所有元素都是相同的。后者由具有X[A] 类型的元素组成,其中A 是任意的,并且对于不同的元素可以是不同的。
  • 是的,既然你提到了它,那就很明显了。在我的辩护中,我在单个值的上下文中使用它,所以自然语言语义相同。

标签: scala types existential-type higher-kinded-types


【解决方案1】:
  • 如果你在High 之外进行存在量化,那么它只是

    type T = High[F] forSome { type F[O] <: UpperBound[O] }
    
    def canEqual(that: Any) = that.isInstanceOf[T]
    
    def high(h: T) = ???
    
  • 如果你在High 内部进行存在量化,那么因为

    implicitly[(n forSome { type n <: Upper}) =:= Upper]
    implicitly[(m[O1] forSome { type m[O] <: UpperBound[O]}) =:= UpperBound[O1]]
    

    (反之亦然)只是High[UpperBound]

    implicitly[High[m forSome { type m[O] <: UpperBound[O] }] =:= High[UpperBound]]
    
    def canEqual(that: Any) = that.isInstanceOf[High[UpperBound]]
    
    def high(h: High[UpperBound]) = ???
    

    存在类型? forSome { ? },其中? 包含子句类型?[tps]&gt;:?&lt;:? 等效于类型?′ forSome { ? },其中?′ 通过替换? 中每个协变出现的? 源自?通过? 并通过? 替换?? 的每个逆变出现。

    https://scala-lang.org/files/archive/spec/2.13/03-types.html#simplification-rules

【讨论】:

  • High 在示例中的类型参数不变,因此不适用替换。给定LowerBound[O] extends UpperBound[O]High[LowerBound] 不是High[UpperBound] 的子类型。
  • 好吧,显然我写的不是我的意思,对不起!我对High[_] 的“已擦除”形式感兴趣,它在isInstanceOf/pattern 中使用时不会触发警告,匹配并且 将是High 的任何实例的超类型。我不知道怎么改,但我会试试的。
  • @Turin 是的,关于你的第一条评论,High 的变化并不显着,重要的是m[O1]m 的出现是协变的,这就是为什么(m[O1] forSome { type m[O] &lt;: UpperBound[O]}) =:= UpperBound[O1] 对于所有@987654351 @.
  • 不过,对于trait Lower[O] exteds UpperBound[O],代码high(new High[Lower]) 无法编译,这让我有点吃惊。要去 SLS 再次阅读该部分,但我觉得我错过了一些明显的东西......
  • @Turin 看起来类型推断有问题。对于type T = High[F] forSome {type F[O] &lt;: UpperBound[O] } def high(h: T) = ???implicitly[High[Lower] &lt;:&lt; T] 编译,new High[Lower] {} : High[Lower] 编译,new High[Lower] {} : T 不编译,high(new High[Lower] {}) 不编译,high(new High[Lower] {} : High[Lower]) 编译,high(new High[Lower] {} : T) 不编译,@987654编译。斯卡拉 2.13.1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-06-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-10-13
  • 2019-08-20
相关资源
最近更新 更多