可以对具有类型符合结果的通用值执行模式匹配吗?
是否可以执行结果符合外部方法的类型参数的模式匹配?例如给出:
trait Key[A] {
def id: Int
def unapply(k: Key[_]): Boolean = k.id == id // used for Fail2
def apply(thunk: => A): A = thunk // used for Fail3
}
trait Ev[A] {
def pull[A1 <: A](key: Key[A1]): Option[A1]
}
trait Test extends Ev[AnyRef] {
val key1 = new Key[String] { def id = 1 }
val key2 = new Key[Symbol] { def id = 2 }
}
是否有 Test
的实现(其 pull
方法),它在 key
参数上使用模式匹配并返回 Option [A1]
检查每个键,而不使用 asInstanceOf
?
一些可悲的尝试:
class Fails1 extends Test {
def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match {
case `key1` => Some("hallo")
case `key2` => Some('welt)
}
}
class Fails2 extends Test {
def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match {
case key1() => Some("hallo")
case key2() => Some('welt)
}
}
class Fails3 extends Test {
def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match {
case k @ key1() => Some(k("hallo"))
case k @ key2() => Some(k('welt))
}
}
显然没有任何效果......唯一的解决方案是强制转换:
class Ugly extends Test {
def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match {
case `key1` => Some("hallo".asInstanceOf[A1])
case `key2` => Some('welt .asInstanceOf[A1])
}
}
val u = new Ugly
u.pull(u.key1)
u.pull(u.key2)
Is it possible to perform a pattern match whose result conforms to a type parameter of the outer method? E.g. given:
trait Key[A] {
def id: Int
def unapply(k: Key[_]): Boolean = k.id == id // used for Fail2
def apply(thunk: => A): A = thunk // used for Fail3
}
trait Ev[A] {
def pull[A1 <: A](key: Key[A1]): Option[A1]
}
trait Test extends Ev[AnyRef] {
val key1 = new Key[String] { def id = 1 }
val key2 = new Key[Symbol] { def id = 2 }
}
Is there an implementation of Test
(its pull
method) which uses a pattern match on the key
argument and returns Option[A1]
for each key checked, without the use of asInstanceOf
?
Some pathetic tries:
class Fails1 extends Test {
def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match {
case `key1` => Some("hallo")
case `key2` => Some('welt)
}
}
class Fails2 extends Test {
def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match {
case key1() => Some("hallo")
case key2() => Some('welt)
}
}
class Fails3 extends Test {
def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match {
case k @ key1() => Some(k("hallo"))
case k @ key2() => Some(k('welt))
}
}
None works, obviously... The only solution is to cast:
class Ugly extends Test {
def pull[A1 <: AnyRef](key: Key[A1]): Option[A1] = key match {
case `key1` => Some("hallo".asInstanceOf[A1])
case `key2` => Some('welt .asInstanceOf[A1])
}
}
val u = new Ugly
u.pull(u.key1)
u.pull(u.key2)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
问题确实在于模式匹配会忽略所有已擦除的类型。然而,人们可以使用一些隐含的技巧。下面将保留返回类型匹配所提供的类型解析。
然而,这几乎等同于仅定义 Key 的单独子类。 我发现以下方法更可取,但是如果现有代码使用 Key[String] 而您无法更改为必要的 KeyString(或者需要更改的工作太多),则它可能不起作用。
The problem is indeed that pattern matching ignores all erased types. However, there is a little implicit trickery that one could employ. The following will preserve the type resolution provided by the match for the return type.
This is however nearly equivalent to just defining separate sub classes of Key. I find the following method preferable however it may not work if existing code is using Key[String] that you can't change to the necessary KeyString (or too much work to change).
我在这里提供了一个基于 Neil Essy 答案的封闭类型方法的扩展示例(显示了我的更多上下文):
然后以下场景编译时没有太多混乱:
...并产生所需的结果:
现在我唯一的事情不明白,我发现丑陋的是我的案件必须是我非常喜欢的形式
,并且不能是
我非常喜欢的形式。有什么想法这个限制来自哪里吗?
I provide here an extended example (that shows more of my context) based on the closed types approach of Neil Essy's answer:
Then the following scenario compiles with not too much clutter:
...and yields the desired results:
Now the only thing I don't get and I find ugly is that my cases must be of the form
and cannot be
which I would very much prefer. Any ideas where this limitation comes from?