如何定义在运行时工作的联合类型?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (7)

接下来就如何在Scala中定义联合类型形成了这一组优秀的答案。我一直在使用Miles Sabin对Union类型的定义,但仍有一个问题。

如果直到运行时才知道类型,你如何使用这些?例如:

trait inv[-A] {}
type Or[A,B] = {
  type check[X] = (inv[A] with inv[B]) <:< inv[X]
}

case class Foo[A : (Int Or String)#check](a: A)

Foo(1)    // Foo[Int] = Foo(1)
Foo("hi") // Foo[String] = Foo(hi)
Foo(2.0)  // Error!

此示例有效,因为参数A在编译时已知,并且调用Foo(1)实际上正在调用Foo[Int](1)。但是,如果A在运行时之前不知道参数,您会怎么做?也许你正在削减包含Foos 的数据的文件,在这种情况下,在Foo读取数据之前不知道类型参数。A在这种情况下,没有简单的方法来设置参数。

我能够提出的最佳解决方案是:

  • 模式匹配您已阅读的数据,然后Foo根据该类型创建不同的数据。在我的情况下,这是不可行的,因为我的case-class实际上包含了几十个union类型,因此有数百种类型的组合来模式匹配。
  • 转换您刚读过的类型(String or Int),因此您只能传递一种类型,在Foo使用它时传递Type Class约束。然后返回Foo[_]。这使得Foo用户有责任计算出每个字段的类型(因为它们看起来是Any类型),但至少在实际使用字段之前它必须知道类型,在这种情况下,模式匹配似乎更容易处理。

第二个解决方案如下所示:

def parseLine: Any // Parses data point, but can be either a String or 
                   // Int, so returns Any.

def mkFoo: Foo[_] = {
  val a = parseLine.asInstanceOf[Int with String]
  Foo(a) // Passes type constraint now
}

在实践中,我最终使用了第二种解决方案,但我想知道我能做些什么更好的事情?

说明问题的另一种方法是:返回联盟类型是什么意思?函数只能返回一个类型,我们与Miles Sabin联合类型一起使用的技巧仅对您传入的类型有用,而不适用于您返回的类型。

PS。对于上下文,为什么在我的情况下这是一个问题是我从Json模式文件生成一组case-classes。Json自然支持联合类型,所以我想让我的案例类也反映出来。这在一个方向上很有用:用户创建要序列化到Json的case-classes。但是在另一个方向变得棘手:用户解析Json文件以返回一组填充的case类。

提问于
用户回答回答于

基于Dotty的下一个Scala 3(2020年中)将从2018年9月开始实施Union Type提案

你在“ Scala 3之旅 ”中看到它(2019年6月)

  • 联合类型提供类型的临时组合
  • 子集=子类型
  • 没有拳击开销

case class UserName(name: String) 
case class Password(hash: Hash) 

def help(id: UserName | Password) = {
  val user = id match { 
    case UserName(name) => lookupName(name) 
    case Password(hash) => lookupPassword(hash) 
  } 
  ... 
}

  • 联合类型也适用于单例类型
  • 非常适合JS互操作

type Command = "Click" | "Drag" | "KeyPressed" 

def handleEvent(kind: Command) = kind match {
  case "Click" => MouseClick() 
  case "Drag" => MoveTo() 
  case "KeyPressed" => KeyPressed() 
} 

热门问答

急急急!!核验图片验证码填写到接入备案企业侧备案系统中,在哪操作啊?

无聊至极互联网重度用户
推荐
你反馈的上海备案的APP核验验证码吗?如果是的话,提交订单的时候直接写验证码就可以的。 在补充材料的下面 image.png ... 展开详请

存储桶和项目概念?

Hyman.W

腾讯云 · 高级产品经理 (已认证)

推荐
一个存储桶对应多个项目的管理方式,可以使用 “标签” 来管理, 在创建存储桶或者修改存储桶配置的页面可以添加。 参考: 1,存储桶标签使用 https://cloud.tencent.com/document/product/436/34830 2,如果需要通过外部系统来管理...... 展开详请

智能钛能处理大数据文件吗?我有30G的数据存储在本地电脑硬盘上?

腾讯智能钛AI开发者

腾讯云 · 智能钛产品团队 (已认证)

腾讯智能钛产品团队官方运营账号。分享产品最新动态,第一时间解答用户疑问。
推荐

硬盘可以升级吗?

最爱开车啦互联网的敏感者
推荐

可以升级,小微活动中没有云硬盘的的,后续可以用同帐号在官网购买和服务器同地域同地区的云硬盘挂载到服务器上使用。

云硬盘挂载初始化方法 可参考 https://cloud.tencent.com/document/product/362/6735

云通信 70402 错误?

推荐已采纳

参数非法,请检查必填字段是否填充,或者字段的填充是否满足协议要求。

您好,可参考此文档:https://cloud.tencent.com/document/product/269/1671

录音识别sdk的录音文件如何保存?

Richel码农
推荐

1.实时语音sdk内置录音器采集音频暂不支持保存语音数据,如需要保存语音数据建议上层自行采集音频数据。

2.实时语音识别sdk不支持暂停&继续操作,停止识别后重新调用start即开始识别。

所属标签

扫码关注云+社区

领取腾讯云代金券