在Scala中可以有一个联合类型的集合吗?here讨论了几种联合类型的方法评分最高的答案感觉最本地化,我有这样的答案:
sealed trait StringOrNumber[T]
object StringOrNumber {
implicit object IntWitness extends StringOrNumber[Int]
implicit object StringWitness extends StringOrNumber[String]
}
但当我试图制作一张既包含这两项内容的Map时
val m: Map[String, Any] = Map("str" -> "hellp", "int" -> 32)
Scala编译器将其视为[字符串,任意]的Map。有什么方法可以告诉Scala编译器这是一个Map[字符串,StringOrNumber]
编辑:
我不认为使用上面的方法可以创建一个字符串或联合的集合。我认为它需要是联合类型的另一种方法,因为上面类似于重载方法,而不是类型系统中真正的联合类型
7条答案
按热度按时间raogr8fs1#
您可以在当前版本的Scala中对运行时联合类型进行最接近的模拟,就是将联合的类型 Package 在Case类中,扩展一些密封的特征。它是样板-y,并在
AnyRef
类型上添加了一个额外的 Package 层,但它是有效的,它比只使用Any
要好,而且您还可以从联合类型添加隐式转换:现在您可以定义您的
Map
:imzjd6km2#
Scala已经有内置的
case
类,能够表示其他类型的任意标记不相交联合。在您的例子中,定义
StringOrNumber
的最简单方法是:如果不想为此创建额外的特征,并且只有两种类型,只需使用
Either
:nkkqxpd93#
您复制的部分答案不完整。有火柴的另一个部分。它表明,这种类型的联合在运行时工作。因此,总的来说,您混合了两种不同的东西:编译时类型Union(也讨论了您提到的问题,最初是由Miles Sabin here编写的),它影响编译器检查,以及运行时类型检查。
所以,一旦您使用运行时方法,Scala编译器就不理解这个联合,并建议使用任何
krugob8w4#
你应该写信给我
这一功能目前正在Dotty开发中。据我所知,这就像是
和
但Dotty将在明年上市。现在,您可以使用您的方法,但它有一点棘手,并且需要暗示。您也可以尝试任何一种类型(只有在您有两个泛型类型的情况下),并且您还可以关注scalaz库。这一切都是关于类型级编程的。
9jyewag05#
你试过了吗:
在这种情况下,您可能还需要显式构造
StringOrNumber
示例才能使其工作。9rygscc16#
让我使用逆方差和类型约束向您介绍我的解决方案:
此解决方案的问题在于,此处不接受Int或字符串的扩展。在此处输入的值被检查为与
Int with String
“相反”。有一种方法可以解决这个问题,您必须绕过类型推断,并在类型参数中提供基类,如下所示:
chy5wohz7#
自那以后,Scala3发布了对联合类型的本机支持。