类型 class 和依赖类型
Type class and dependent types
首先,我不知道如何正确标记我的问题。这也可能是我找不到有用资源的原因。非常感谢任何提示。
trait Context[T]
{
self =>
trait Rule
{
def apply( value: T ): Boolean
}
implicit class RichRule[A <: Rule]( a: A )
{
def and[B <: Rule]( b: B ): and[A, B] = self.and( a, b )
def or[B <: Rule]( b: B ): or[A, B] = self.or( a, b )
}
sealed trait Group[A <: Rule, B <: Rule] extends Rule
{
def a: A
def b: B
override def apply( value: T ) = ???
}
case class and[A <: Rule, B <: Rule]( a: A, b: B ) extends Group[A, B]
case class or[A <: Rule, B <: Rule]( a: A, b: B ) extends Group[A, B]
}
鉴于上面的代码,我现在可以用这种方式定义和链接 Rules
s:
new Context[String]
{
class MyRule extends Rule
{
override def apply( value: String ) = true
}
case class A() extends MyRule
case class B() extends MyRule
val x1: A and B or A = A() and B() or A()
}
这按我的预期工作,但现在是棘手的部分。我想介绍一个类型 Class Combination
来解释如何连接两个规则。
trait Combination[-A <: Rule, -B <: Rule]
{
type Result <: Rule
def combine( a: A, b: B ): Result
}
trait AndCombination[-A <: Rule, -B <: Rule] extends Combination[A, B]
trait OrCombination[-A <: Rule, -B <: Rule] extends Combination[A, B]
现在应使用运算符传递此类型 Class。
implicit class RichRule[A <: Rule]( a: A )
{
def and[B <: Rule]( b: B )( implicit c: AndCombination[A, B] ): and[A, B] = ???
def or[B <: Rule]( b: B )( implicit c: OrCombination[A, B] ): or[A, B] = self.or( a, b )
}
经过一些调整后仍然有效。
implicit val c1 = new Combination[MyRule, MyRule]
{
type Result = MyRule
def combine( a: A, b: B ): MyRule = a
}
val x: A and B = A() and B()
但如果它变得更复杂,事情就会分崩离析。
A() and B() and A()
将引发隐式缺失错误:Combination[and[A, B], A]
缺失。但我希望它使用它已经知道如何处理的 and[A, B]
(type Result = MyRule
) 的隐式组合的结果 (Combination[and[A, B]#Result, A]
).
保留组合规则的类型信息对我来说很重要val x: A and B or A
,将它们折叠成最终结果类型很容易,但不是我想要的。
这是我所能得到的最接近的结果,但是编译失败。
trait Context[T]
{
self =>
trait Rule
trait Value extends Rule
trait Group[A <: Rule, B <: Rule] extends Rule
{
def a: A
def b: B
implicit val resolver: Resolver[_ <: Group[A, B]]
}
case class and[A <: Rule, B <: Rule]( a: A, b: B )( implicit val resolver: Resolver[and[A, B]] ) extends Group[A, B]
implicit class RichRule[A <: Rule]( a: A )
{
def and[B <: Rule]( b: B )( implicit resolver: Resolver[and[A, B]] ) = self.and[A, B]( a, b )
}
trait Resolver[-A <: Rule]
{
type R <: Value
def resolve( a: A ): R
}
}
object O extends Context[String]
{
implicit val c1 = new Resolver[A and A]
{
override type R = A
override def resolve( a: O.and[A, A] ) = ???
}
implicit def c2[A <: Value, B <: Value, C <: Value]( implicit r1: Resolver[A and B] ) = new Resolver[A and B and C]
{
override type R = C
override def resolve( a: A and B and C ): C =
{
val x: r1.R = r1.resolve( a.a )
new c2( x )
???
}
}
class c2[A <: Value, B <: Value]( val a: A )( implicit r2: Resolver[A and B] ) extends Resolver[A and B]
{
override type R = B
override def resolve( a: O.and[A, B] ) = a.b
}
case class A() extends Value
val x: A and A and A = A() and A() and A()
}
您的代码无法编译的原因是在指令中
new c2( x )
编译器需要从x
解析implicit r2: Resolver[A and B]
,唯一可用的类型信息是x
的类型,即r1.R
。
此类问题需要为编译器提供更多类型信息并添加一些隐式参数。当您需要一个 Resolver[A and B]
时,您不能使用它的 R
类型来解析另一个 Resolver[r1.R and C]
.
type ResolverAux[-A<:Rule,B] = Resolver[A] { type R = B }
有了这个,您可以重写您的 c2 的签名
implicit def c2[A <: Value, B <: Value, C <: Value,D<:Value]( implicit r1: ResolverAux[A and B,D], r2:Resolver[D and C] ):Resolver[A and B and C] = new Resolver[A and B and C]
{
override type R = C
override def resolve( a: A and B and C ): C =
{
val x: r1.R = r1.resolve( a.a )
new c2[r1.R,C]( x )
???
}
}
请注意,通过使用类型别名并引入一个额外的泛型参数,我可以表达关系 r1.R1 = D
,然后用于解析第二个隐式 r2
首先,我不知道如何正确标记我的问题。这也可能是我找不到有用资源的原因。非常感谢任何提示。
trait Context[T]
{
self =>
trait Rule
{
def apply( value: T ): Boolean
}
implicit class RichRule[A <: Rule]( a: A )
{
def and[B <: Rule]( b: B ): and[A, B] = self.and( a, b )
def or[B <: Rule]( b: B ): or[A, B] = self.or( a, b )
}
sealed trait Group[A <: Rule, B <: Rule] extends Rule
{
def a: A
def b: B
override def apply( value: T ) = ???
}
case class and[A <: Rule, B <: Rule]( a: A, b: B ) extends Group[A, B]
case class or[A <: Rule, B <: Rule]( a: A, b: B ) extends Group[A, B]
}
鉴于上面的代码,我现在可以用这种方式定义和链接 Rules
s:
new Context[String]
{
class MyRule extends Rule
{
override def apply( value: String ) = true
}
case class A() extends MyRule
case class B() extends MyRule
val x1: A and B or A = A() and B() or A()
}
这按我的预期工作,但现在是棘手的部分。我想介绍一个类型 Class Combination
来解释如何连接两个规则。
trait Combination[-A <: Rule, -B <: Rule]
{
type Result <: Rule
def combine( a: A, b: B ): Result
}
trait AndCombination[-A <: Rule, -B <: Rule] extends Combination[A, B]
trait OrCombination[-A <: Rule, -B <: Rule] extends Combination[A, B]
现在应使用运算符传递此类型 Class。
implicit class RichRule[A <: Rule]( a: A )
{
def and[B <: Rule]( b: B )( implicit c: AndCombination[A, B] ): and[A, B] = ???
def or[B <: Rule]( b: B )( implicit c: OrCombination[A, B] ): or[A, B] = self.or( a, b )
}
经过一些调整后仍然有效。
implicit val c1 = new Combination[MyRule, MyRule]
{
type Result = MyRule
def combine( a: A, b: B ): MyRule = a
}
val x: A and B = A() and B()
但如果它变得更复杂,事情就会分崩离析。
A() and B() and A()
将引发隐式缺失错误:Combination[and[A, B], A]
缺失。但我希望它使用它已经知道如何处理的 and[A, B]
(type Result = MyRule
) 的隐式组合的结果 (Combination[and[A, B]#Result, A]
).
保留组合规则的类型信息对我来说很重要val x: A and B or A
,将它们折叠成最终结果类型很容易,但不是我想要的。
这是我所能得到的最接近的结果,但是编译失败。
trait Context[T]
{
self =>
trait Rule
trait Value extends Rule
trait Group[A <: Rule, B <: Rule] extends Rule
{
def a: A
def b: B
implicit val resolver: Resolver[_ <: Group[A, B]]
}
case class and[A <: Rule, B <: Rule]( a: A, b: B )( implicit val resolver: Resolver[and[A, B]] ) extends Group[A, B]
implicit class RichRule[A <: Rule]( a: A )
{
def and[B <: Rule]( b: B )( implicit resolver: Resolver[and[A, B]] ) = self.and[A, B]( a, b )
}
trait Resolver[-A <: Rule]
{
type R <: Value
def resolve( a: A ): R
}
}
object O extends Context[String]
{
implicit val c1 = new Resolver[A and A]
{
override type R = A
override def resolve( a: O.and[A, A] ) = ???
}
implicit def c2[A <: Value, B <: Value, C <: Value]( implicit r1: Resolver[A and B] ) = new Resolver[A and B and C]
{
override type R = C
override def resolve( a: A and B and C ): C =
{
val x: r1.R = r1.resolve( a.a )
new c2( x )
???
}
}
class c2[A <: Value, B <: Value]( val a: A )( implicit r2: Resolver[A and B] ) extends Resolver[A and B]
{
override type R = B
override def resolve( a: O.and[A, B] ) = a.b
}
case class A() extends Value
val x: A and A and A = A() and A() and A()
}
您的代码无法编译的原因是在指令中
new c2( x )
编译器需要从x
解析implicit r2: Resolver[A and B]
,唯一可用的类型信息是x
的类型,即r1.R
。
此类问题需要为编译器提供更多类型信息并添加一些隐式参数。当您需要一个 Resolver[A and B]
时,您不能使用它的 R
类型来解析另一个 Resolver[r1.R and C]
.
type ResolverAux[-A<:Rule,B] = Resolver[A] { type R = B }
有了这个,您可以重写您的 c2 的签名
implicit def c2[A <: Value, B <: Value, C <: Value,D<:Value]( implicit r1: ResolverAux[A and B,D], r2:Resolver[D and C] ):Resolver[A and B and C] = new Resolver[A and B and C]
{
override type R = C
override def resolve( a: A and B and C ): C =
{
val x: r1.R = r1.resolve( a.a )
new c2[r1.R,C]( x )
???
}
}
请注意,通过使用类型别名并引入一个额外的泛型参数,我可以表达关系 r1.R1 = D
,然后用于解析第二个隐式 r2