从嵌套类型获取子类型

时间:2019-01-14 08:39:41

标签: scala

我看不到获取嵌套类型子类型的方法,有可能吗?

type IN[A,B] = {
  type X = A
  type Y = B
}

trait INH[IN[A,B]] {
  type X = IN#X
  type Y = IN#Y 
}

但这无法编译...

更新 我将扩展这种情况:
有一些类:A,B,C,N-是状态类,我想实现路径依赖的对象:

  1. C -必须仅从 A B
  2. 初始化
  3. D -必须仅从 A B C
  4. 初始化
abstract class State

trait UN[T <: |∨|[_, _]] {
  type U[I] = T#λ[I]
}

case class A() extend State
case class B() extend State
case class C(state: State) extend State with UN[(A |∨| B)]
case class D(state: State) extend State with UN[(A |∨| B |∨| C)]
case class Z() extend State

因此,联合类型的Curry Howard定义是:

type ![S] = S => Nothing
type !![S] = ![![S]]
type ∨[T, U] = ![![T] with ![U]]
type |∨|[T, U] = { type λ[X] = !![X] <:< (T ∨ U) }

所以我试图做类似的事情,但是没有成功:

case class C(state: State) {
   def test[T <: State](t:T)(implicit ev: (A |∨| B)#λ[T]) = {}
   def apply[T <: State](state: T)(implicit ev: (A |∨| B)#λ[T]) = C(state)
}

val a = A(); val b = B(); val z = Z()
val ca = C(a); val cb = C(b)
ca.test(a) // compilation OK
val cz = C(n) // that shouldn't compile but it's

2 个答案:

答案 0 :(得分:2)

您必须按照以下方式进行操作:

trait IN[A, B] {
  type X = A
  type Y = B
}

trait INH[T <: IN[_, _]] {
  type X = T#X
  type Y = T#Y
}

答案 1 :(得分:0)

talex的答案是正确的,但请注意,Scala 3中将不允许在抽象类型成员上进行这种类型投影(在2020年之前不会出现)。

您的用例似乎有点奇怪,为什么不简单地将IN声明为

trait IN {
    type A
    type B
}

然后,您可以直接以A的身份访问IN#A,或者最好在Scala 3中允许访问in的实例IN,并以in.A身份访问。

如果您想以简明的方式约束AB或两者,则可以使用类型细化并定义别名:

type INWithSpecificA[+AA] = IN {
    type A <: AA
}

B也一样。我个人发现,这种设计比talex的建议更具灵活性。