Scala 中的通用递归类型

3

我刚开始涉猎Scala,现在想了解是否有办法在Scala中表达深度部分类型(递归类型)?

###################### 更新 ######################

我的目标是获取一个现有的case class并以某种方式“版本化”它,使其递归地添加到每个字段,即使是在深度嵌套的级别。

例如,假设我已经定义了这些类:

case class A(p1: Int, p2: Int, ..)
case class B(p1: Map[String, A])
case class C(param1: String, param2: String, param3: Option[B]) 

我想要对C进行版本控制,这意味着对于每个参数类型(递归地),我都希望添加一个可选的version: Int
我看到的一种朴素方法是定义一个新类VersionedValue,然后手动重新定义所有现有类型以适应此更改。
例如,它可能看起来像这样:
case class VersionedValue [A](value: A, version: Option[Int])

case class A(p1: VersionedValue[Int], p2: VersionedValue[Int])

case class B(p1: Map[String, VersionedValue[A]])

case class C(p1: VersionedValue[String], 
             p2: VersionedValue[String],
             p3: Option[B]) 

在使用 TypeScript 一段时间之后,通常会看起来像这样:

/** 
* the VersionedDeepPartial<T> will recursively iterate through 
* each of the "keys" (or attributes) and for each creates a new
* object that adds a version field. The value attribute will hold 
* what was originally the type for the key.
*/
export type VersionedDeepPartial<T> = {
  [P in keyof T]?: {value: VersionedDeepPartial<T[P]>; version?:number}
};

// So if I had an interface (in typescript) looking like:

interface A {
  p1: number,
  p2: number,
}

interface B {
   [key: string]: A
}

interface C {
   p1: String,
   p2: String,
   p3: B
}

/**
* Note that interface C does not define any versioning attribute to
* its fields. But by wrapping the type within the 
*/
VersionedDeepPartial<T>

const partialFoo: VersionedDeepPartial<C> = {
    p1: { value: "asdf", version: 1 },
    p2: { value: "asdf" },
    p3: {
        "somekey": {
           p1: {value: 1, version: 1},
           p2: {value: 2}
    }
} 

基本上,我想通过递归遍历现有类型/类定义并向其中“注入”版本控制来定义一个新的类型。

我已经阅读/浏览了关于此主题的说明,但没有成功。在Scala中是否可能表达这个想法?


我认为这需要宏或类似shapeless的库。有趣的是,是否可以使用Scala 3中的任何功能来实现此功能(Mirror?)。 - ziggystar
1
我很好奇你想用这个解决什么问题?我怀疑在Scala中有更好的静态类型解决方案。 - Jack Leow
@texasbruce ^ TS 代码中的 DeepPartial 类型定义是一种有效地使现有类型中的每个属性变为可选的方法。这样,您就可以实例化或验证类型的部分数据。对于我的用例,我想避免复制粘贴我复杂类型的类型定义。虽然在 TS 中这是完全可以实现的,但我还没有找到在 Scala 中实现的方法。 - me_L_coding
不确定为什么这不需要递归要求?在给出的TypeScript示例中,它将递归地遍历每个对象属性类型,只是我将其包装以添加版本控制。在scala示例中,我仍然需要对C案例类的每个成员进行版本控制,它们的成员也需要进行版本控制,依此类推。我正在处理的模型可能有多达5-7级嵌套类型。不熟悉宏,但会看一下@sarveshseri - me_L_coding
https://dev59.com/2LPma4cB1Zd3GeqPn0Y8 - Dmytro Mitin
显示剩余3条评论
1个回答

0

你可能想要使用更高级的数据类型方法:

case class HKDA[F[_]](p1: F[Int], p2: F[Int], ..)
case class HKDB[F[_]](p1: Map[String, HKDA[F]])
case class HKDC[F[_]](param1: F[String], param2: F[String], param3: Option[HKDB[F]])

type Id[A] = A
type A = HKDA[Id]
type B = HKDB[Id]
type C = HKDC[Id]

case class Versioned[A](a: A, version: Int)
type VersionedA = HKDA[Versioned]
type VersionedB = HKDB[Versioned]
type VersionedC = HKDC[Versioned]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接