猿问

如何定义“类型分离”(联合类型)?

如何定义“类型分离”(联合类型)?

有一种方法建议处理重载方法的双重定义是将重载替换为模式匹配:

object Bar {
   def foo(xs: Any*) = xs foreach { 
      case _:String => println("str")
      case _:Int => println("int")
      case _ => throw new UglyRuntimeException()
   }}

这种方法要求我们提交对参数的静态类型检查。foo..如果能写的话会好得多

object Bar {
   def foo(xs: (String or Int)*) = xs foreach {
      case _: String => println("str")
      case _: Int => println("int")
   }}

我可以接近Either,但它很快就会变得丑陋,有两种以上的类型:

type or[L,R] = Either[L,R]implicit def l2Or[L,R](l: L): L or R = Left(l)implicit def r2Or[L,R](r: R): L or R = Right(r)object Bar {
   def foo(xs: (String or Int)*) = xs foreach {
      case Left(l) => println("str")
      case Right(r) => println("int")
   }}

它看起来像是一个通用的(优雅的,高效的)解决方案需要定义Either3Either4..有谁知道实现同样目的替代解决方案吗?据我所知,Scala没有内置的“类型分离”。另外,上面定义的隐式转换是否潜伏在某个标准库中,以便我只需导入它们?


交互式爱情
浏览 427回答 3
3回答

慕容708150

嗯,在具体的案例中Any*,下面这个技巧不会起作用,因为它不会接受混合类型。但是,由于混合类型也不能处理重载,所以这可能是您想要的。首先,使用您希望接受的类型声明一个类,如下所示:class StringOrInt[T]object StringOrInt {   implicit object IntWitness extends StringOrInt[Int]   implicit object StringWitness extends StringOrInt[String]}接下来,声明foo就像这样:object Bar {   def foo[T: StringOrInt](x: T) = x match {     case _: String => println("str")     case _: Int => println("int")   }}仅此而已。你可以打电话foo(5)或foo("abc"),它会起作用的,但是试一试foo(true)就会失败。客户端代码可以通过创建StringOrInt[Boolean],除非,如兰德尔下面,你做StringOrInta sealed班级,等级。它起作用是因为T: StringOrInt意味着有一个隐式参数StringOrInt[T],因为Scala在类型的伴生对象中查找,以查看是否存在使请求该类型的代码工作的隐式。

红糖糍粑

下面是Rex Kerr编码联合类型的方法。直截了当!scala>&nbsp;def&nbsp;f[A](a:&nbsp;A)(implicit&nbsp;ev:&nbsp;(Int&nbsp;with&nbsp;String)&nbsp;<:<&nbsp;A)&nbsp;=&nbsp;a&nbsp;match&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;case&nbsp;i:&nbsp;Int&nbsp;=>&nbsp;i&nbsp;+&nbsp;1 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;case&nbsp;s:&nbsp;String&nbsp;=>&nbsp;s.length&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;}f:&nbsp;[A](a:&nbsp;A)(implicit&nbsp;ev:&nbsp;<:<[Int&nbsp;with&nbsp;String,A])Intscala>&nbsp;f(3)res0: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Int&nbsp;=&nbsp;4scala>&nbsp;f("hello")res1:&nbsp;Int&nbsp;=&nbsp;5scala>&nbsp;f(9.2)<console>:9:&nbsp;error:&nbsp;Cannot&nbsp;prove&nbsp;that&nbsp;Int&nbsp;with&nbsp;String&nbsp;<:<&nbsp;Double. &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;f(9.2) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;^资料来源:第27条评论这,这个MilesSabin的优秀博客文章提供了在Scala中编码联合类型的另一种方式。
随时随地看视频慕课网APP
我要回答