给定以下枚举:
enum Connector:
case CHAdeMO
case Mennekes
case CCS
case Tesla
Run Code Online (Sandbox Code Playgroud)
是否有类似Map[ConnectorType, Int]但会产生编译错误的类型:
Map(
Connector.CHAdeMO -> 1,
Connector.Mennekes -> 2,
Connector.CCS -> 3,
)
Run Code Online (Sandbox Code Playgroud)
也就是说,地图不包含 的键Connector.Tesla。换句话说,在编译时,类型应该类似于((Connector.CHAdeMO, Int), (Connector.Mennekes, Int), (Connector.CCS, Int), (Connector.Tesla, Int))常规 Map,但在其他方面表现得像常规 Map。
这是使用元组( Scastie )的解决方案:
opaque type CheckedMap <: Map[Connector, Int] = Map[Connector, Int]
type Contains[E, T <: Tuple] <: Boolean = T match {
case EmptyTuple => false
case h *: t =>
h match {
case (E, _) => true
case _ => Contains[E, t]
}
}
type ContainsAll[S <: Tuple, T <: Tuple] = S match {
case EmptyTuple => DummyImplicit
case h *: t =>
Contains[h, T] match {
case true => ContainsAll[t, T]
case false => Nothing
}
}
type AllConnectors = (
Connector.CHAdeMO.type,
Connector.Mennekes.type,
Connector.CCS.type,
Connector.Tesla.type
)
def checkedMap[T <: Tuple](t: T)(using
@annotation.implicitNotFound(
"Not all Connector types given."
) c: ContainsAll[AllConnectors, T]
): CheckedMap = t.toList.asInstanceOf[List[(Connector, Int)]].toMap
Run Code Online (Sandbox Code Playgroud)
这将采用一个元组的元组(Connector, Int),并检查它是否包含另一个所有类型元组中的所有类型Connector。如果输入至少包含一次所有连接器类型,则它会查找隐式DummyImplicit,否则,它会查找隐式Nothing,但显然找不到。生成的错误消息相当冗长且无用,因此我输入了自定义错误消息。请注意,这不会检查是否存在重复的键,但可以进行简单的修改来执行此操作。
不幸的是,我发现自己必须在使用站点显式注释键值对的类型:
//Errors because Tesla is missing
checkedMap(
(
Connector.CHAdeMO -> 1: (Connector.CHAdeMO.type, Int),
Connector.Mennekes -> 2: (Connector.Mennekes.type, Int),
Connector.CCS -> 3: (Connector.CCS.type, Int)
)
)
//Valid
checkedMap(
(
Connector.CHAdeMO -> 1: (Connector.CHAdeMO.type, Int),
Connector.Mennekes -> 2: (Connector.Mennekes.type, Int),
Connector.CCS -> 3: (Connector.CCS.type, Int),
Connector.Tesla -> 4: (Connector.Tesla.type, Int)
)
)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
146 次 |
| 最近记录: |