You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Scala 2.13实现输入类型决定输出类型的编译时检查函数

编译时约束输入输出类型的Scala 2.13实现方案

以下两种方案均可实现需求中的编译时检查,无需依赖外部库:


方案一:路径依赖类型 + 中间特质

通过新增中间特质调整Out层级,结合路径依赖类型直接约束输入输出的对应关系:

1. 调整类型层级

新增Out1OrOut11特质限定In1允许的输出范围,同时为In的子类定义路径依赖类型:

trait In {
  // 该输入类型允许的输出类型
  type AllowedOut <: Out
}
trait Out

// 新增中间特质,限定In1可返回的输出类型
trait Out1OrOut11 extends Out
case class In1() extends In {
  type AllowedOut = Out1OrOut11
}
case class In2() extends In {
  type AllowedOut = Out2
}

case class Out1() extends Out1OrOut11
case class Out11() extends Out1OrOut11
case class Out2() extends Out

2. 实现约束函数

利用路径依赖类型作为返回值,确保编译时验证类型合法性:

def process[I <: In](in: I): in.AllowedOut = in match {
  case _: In1 => Out1().asInstanceOf[in.AllowedOut]
  case _: In2 => Out2().asInstanceOf[in.AllowedOut]
}

验证效果

  • 合法调用(编译通过):
    val res1: Out1 = process(In1())   // 允许返回Out1
    val res11: Out11 = process(In1()) // 允许返回Out11
    val res2: Out2 = process(In2())   // 允许返回Out2
    
  • 非法调用(编译报错):
    // 编译错误:类型不匹配,无法将In1#AllowedOut转换为Out2
    val invalid: Out2 = process(In1())
    

方案二:类型类实现

无需修改原有类型层级,通过类型类标记合法的输入输出组合:

1. 定义类型类

创建类型类AllowedIO,为合法的输入输出组合提供隐式实例:

trait In
trait Out

case class In1() extends In
case class In2() extends In

case class Out1() extends Out
case class Out11() extends Out
case class Out2() extends Out

// 类型类:标记I类型输入允许返回O类型输出
trait AllowedIO[I <: In, O <: Out]

// 注册合法的输入输出组合
object AllowedIO {
  implicit val in1ToOut1: AllowedIO[In1, Out1] = new AllowedIO[In1, Out1] {}
  implicit val in1ToOut11: AllowedIO[In1, Out11] = new AllowedIO[In1, Out11] {}
  implicit val in2ToOut2: AllowedIO[In2, Out2] = new AllowedIO[In2, Out2] {}
}

2. 实现约束函数

通过隐式参数AllowedIO[I, O]限制返回类型,只有合法组合能通过编译:

import AllowedIO._

def process[I <: In, O <: Out](in: I)(implicit ev: AllowedIO[I, O]): O = in match {
  case _: In1 => 
    // 可根据逻辑返回Out1或Out11,asInstanceOf因隐式证据保证类型安全
    scala.util.Random.nextBoolean() match {
      case true => Out1().asInstanceOf[O]
      case false => Out11().asInstanceOf[O]
    }
  case _: In2 => Out2().asInstanceOf[O]
}

验证效果

  • 合法调用(编译通过):
    val res1: Out1 = process(In1())
    val res11: Out11 = process(In1())
    val res2: Out2 = process(In2())
    
  • 非法调用(编译报错):
    // 编译错误:找不到AllowedIO[In1, Out2]的隐式值
    val invalid: Out2 = process(In1())
    

方案选择

  • 方案一适合可调整原有类型层级的场景,代码逻辑更直观;
  • 方案二无需修改原有类型结构,灵活性更强。

内容的提问来源于stack exchange,提问作者Pizza eu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 22:47:09