我有Conjuction类型
type ![S] = S => Nothing
type !![S] = ![![S]]
type ∨[T, U] = ![![T] with ![U]]
type |∨|[T, U] = {type λ[X] = !![X] <:< (T ∨ U)}
类层次结构:a,b,c,d,n
abstract class State
case class A() extends State
case class B() extends State
case class N() extends State
// what should i place in ??? , state.type doesn't compile :
// Error: not found value state ... in evidence
case class C(state: State)(implicit ev: (A |∨| B)#λ[???])
case class D(state: State)(implicit ev: (A |∨| B |∨| C)#λ[???])
样本:
val a = A(); val b = B(); val n = N()
val ca = C(a); val cb = C(b)
//this shouldn't compile because evidence (A |∨| B)
val cn = C(n)
如何以正确的方式实施证据?
答案 0 :(得分:0)
尝试对案例类进行参数化
type ![S] = S => Nothing
type !![S] = ![![S]]
type ∨[T, U] = ![![T] with ![U]]
type |∨|[T, U] = {type λ[X] = !![X] <:< (T ∨ U)}
abstract class State
case class A() extends State
case class B() extends State
case class N() extends State
case class C[S <: State](state: S)(implicit ev: (A |∨| B)#λ[S])
val a = A()
val b = B()
val n = N()
val ca = C(a)
val cb = C(b)
// val cn = C(n) // doesn't compile
编码更多类
type ![S] = S => Nothing
type !![S] = ![![S]]
trait Disj[T] {
type or[S] = Disj[T with ![S]]
type apply = ![T]
}
// for convenience
type disj[T] = { type or[S] = Disj[![T]]#or[S] }
type w[T, U, V] = disj[T]#or[U]#or[V]#apply
type ww[T, U, V] = {type λ[X] = !![X] <:< w[T, U, V]}
abstract class State
case class A() extends State
case class B() extends State
case class C() extends State
case class N() extends State
case class D[S <: State](state: S)(implicit ev: ww[A, B, C]#λ[S])
val a = A()
val b = B()
val c = C()
val n = N()
val da = D(a)
val db = D(b)
val dc = D(c)
// val dn = D(n) // doesn't compile
或者您可以使用apply
方法
type ![S] = S => Nothing
type !![S] = ![![S]]
type ∨[T, U] = ![![T] with ![U]]
type |∨|[T, U] = {type λ[X] = !![X] <:< (T ∨ U)}
abstract class State
case class A() extends State
case class B() extends State
case class N() extends State
class C private(state: State)
object C {
def apply(state: State)(implicit ev: (A |∨| B)#λ[state.type]) = new C(state)
}
val a = A()
val b = B()
val n = N()
val ca = C(a)
val cb = C(b)
// val cn = C(n) // doesn't compile
如果您想使用apply
方法避免伴随对象(出于某种原因),可以考虑使用辅助构造函数
type ![S] = S => Nothing
type !![S] = ![![S]]
type ∨[T, U] = ![![T] with ![U]]
type |∨|[T, U] = {type λ[X] = !![X] <:< (T ∨ U)}
abstract class State
case class A() extends State
case class B() extends State
case class N() extends State
// "ignored" is to avoid constructor ambiguity
class C private(state: State, ignored: Int) {
def this(state: State)(implicit ev: (A |∨| B)#λ[state.type]) = this(state, 0)
}
val a = A()
val b = B()
val n = N()
val ca = new C(a)
val cb = new C(b)
// val cn = new C(n) // doesn't compile
使用辅助构造函数或伴随对象的apply
方法是处理构造函数(1 2 3中这种依赖关系的一种标准解决方法。另一种选择是等待Dotty中的实际联合类型(当前方法只是对它们的部分仿真)或在Scala中解析SI-5712。
要自动生成伴随对象,可以考虑使用宏或代码生成。