具有类型成员的案例对象的模式匹配 [英] Pattern Match on Case Objects with Type Members

查看:88
本文介绍了具有类型成员的案例对象的模式匹配的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Scala具有一个很好的功能,可以在模式匹配中推断类型参数.它还检查模式匹配的穷举性.例如:

Scala has a nice feature to infer type parameter inside the pattern match. It also checks pattern match exhaustiveness. For example:

sealed trait PField[T]

case object PField1 extends PField[String]

case object PField2 extends PField[Int]

def getValue[X](f: PField[X]): X = f match {
  case PField1 => "aaa"
  case PField2 => 123
}

是否可以实现相同的功能,但使用类型成员而不是类型参数?

sealed trait Field {
  type T
}

case object Field1 extends Field {
  type T = String
}

case object Field2 extends Field {
  type T = Int
}

以下解决方案不起作用(在Scala 2.12.6中测试):

Following solutions do not work (Tested in Scala 2.12.6):

//No exhaustiveness check
def getValue[X](f: Field {type T = X}): X = f match {
  case Field1 => "aaa"
  //    case Field2 => 123
}

//casting needed
def getValue2[X](f: Field {type T = X}): X = (f: Field) match {
  case Field1 => "aaa".asInstanceOf[X]
  case Field2 => 123.asInstanceOf[X]
}

type Generified[X] = Field {type T = X}

//No exhaustiveness check
def getValue3[X](f: Generified[X]): X = f match {
  case Field1 => "aaa"
  //    case Field2 => 123
}

在我的情况下,

类型参数确实存在问题,因为我有许多字段子层次结构,并且每个层次结构都有一些类型类.我不能将所有需要的依赖项放在case对象的内部,因为它们以瘦JAR格式导出到客户端.

Type parameter is really problematic in my case because I have many sub-hierarchies of Fields and each hierarchy have some type classes. I can't put all the needed dependencies inside case object's because they are exported in a thin JAR to clients.

推荐答案

此解决方案是@Andrey Tyukin发布的解决方案的简化版本. 他说

This solution is a simplified version of solution posted by @Andrey Tyukin. He stated that

对于Field3类型的任意两个值a,b,不认为a.T = b.T.

it does not hold that a.T = b.T for any two values a, b of type Field3.

这意味着,要进行详尽的模式匹配,必须忽略类型成员.因此,为了同时具有穷举性和类型推断性,我们需要使用类型参数进行密封的层次结构.

It means that, to have exhaustive pattern match, type members must be ignored. So in order to have both exhaustiveness and type inference we need sealed hierarchy with type parameters.

他建议为案例类和模式匹配创建单独的层次结构,而不是在主层次结构上进行模式匹配.但是,在我的情况下,它可以简化:我使用类型参数创建了新的密封特征,但相同的案例对象用于模式匹配(唯一保证"保留在对象本身中).这是最终解决方案:

He suggested to create separate hierarchy of case classes and pattern match on them instead of on the main hierarchy. However in my case it can be simplified: I created new sealed trait with type parameter but the same case objects are used for pattern match ("unique guarantee" is held in the object itself). This is final solution:

sealed trait Field {
  type T
  def ug: TField[T]
}

sealed trait TField[G] extends Field {
  type T = G
  def ug: TField[T] = this
}

case object Field1 extends TField[String]
case object Field2 extends TField[Int]

def getValue[X](f: Field {type T = X}): X = (f.ug: TField[X]) match {
  case Field1 => "abc"
  case Field2 => 123
}

由于我可以使用Field特征来定义类型类,而无需进入更高种类的类型,而切换到TField[G]进行模式匹配.

Thanks to that I can use Field trait to define type classes without going into higher kinded types and switch into TField[G] for pattern match.

这篇关于具有类型成员的案例对象的模式匹配的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆