Scala 如何使用相同的类型参数实施ADT
我有以下ADT:Scala 如何使用相同的类型参数实施ADT,scala,generics,domain-driven-design,algebraic-data-types,Scala,Generics,Domain Driven Design,Algebraic Data Types,我有以下ADT: sealed trait Event case class EventA(id: Int) extends Event case class EventB(id: Int) extends Event case object EventDontCare extends Event object Event { def test(ev: Event) = ev match { case EventA(x) => x case EventB(y)
sealed trait Event
case class EventA(id: Int) extends Event
case class EventB(id: Int) extends Event
case object EventDontCare extends Event
object Event {
def test(ev: Event) = ev match {
case EventA(x) => x
case EventB(y) => y + 1
case EventDontCare => 0
}
}
val eva = EventA(10)
println(Event.test(eva))
它工作得很好,但是现在我需要有两个独立的类型,一个使用Int作为上面的id,另一个使用String作为id。
我已尝试将类型参数添加到事件特征:
sealed trait GEvent[ID]
case class GEventA[ID](id: ID) extends GEvent[ID]
case class GEventB[ID](id: ID) extends GEvent[ID]
object EventInt {
type Event = GEvent[Int]
type EventA = GEventA[Int]
type EventB = GEventB[Int]
case object EventDontCare extends GEvent[Int]
def test(ev: Event) = ev match {
case x: EventA => x.id
case y: EventB => y.id + 1
case EventDontCare => 0
}
}
object EventString {....}
val evi = new EventInt.EventA(10)
val evii = GEventA[Int](10)
val evd = EventInt.EventDontCare
println(EventInt.test(evd))
println(EventInt.test(evi))
println(EventInt.test(evii))
我想问几个问题:
是否有更好的方法将类型注入ADT的所有成员?我对上述方法不满意。
在测试方法中的模式匹配中,为什么不能使用case EventAx=>或事件case GEventA[Int]x=>?
同样,为什么我必须用new关键字创建evi变量?
即使我已经涵盖了所有3种情况,为什么编译器仍然警告我:
匹配可能并不详尽。它将在以下输入上失败:
EventDontCare
但它仍然正确运行,为DontCare案例打印10
我认为你说的是对的。我建议您一起定义ADT,现在您已经分别定义了EventDont。此外,由于基本trait事件没有id,因此在那里强制类型是没有意义的。因此,我会将您的ADT改写为:
sealed trait Event
case class GEventA[ID](id: ID) extends Event
case class GEventB[ID](id: ID) extends Event
case object EventDontCare extends Event
模式匹配可以这样重新编写,以包括成员上的类型
def test(ev: Event) = ev match {
case GEventA(id:Int) => id
case GEventB(id:Int) => id + 1
case EventDontCare => 0
}
输入这个,我没有得到你提到的警告
最后,您观察到的类型别名是Scala中的工作方式。如果为案例类定义类型别名,则在不使用new的情况下,无法使用别名定义实例
可选部分
这里是ADT的另一种定义,它将id与其他实体解耦
sealed trait Event
case object GEventA extends Event
case object GEventB extends Event
case object EventDontCare extends Event
case class IdEvent[A, E <: Event](id: A, e: E) extends Event
这里的好处是,您不会因为id的详细信息而污染您的所有实体。Humm类型的擦除会导致问题吗?