[英]Why doesn't scala infer the type members of an inherited trait?
我有一组类型,每个类型都有自己的类型成员:
sealed trait FieldType {
type Data
def parse(in: String): Option[Data]
}
object Name extends FieldType {
type Data = String
def parse(in: String) = Some(in)
}
object Age extends FieldType {
type Data = Int
def parse(in: String) = try { Some(in.toInt) } catch { case _ => None }
}
我有一组类型可以在FieldType
的集合上运行(使用样板而不是抽象的arity):
sealed trait Schema {
type Schema <: Product
type Data <: Product
val schema: Schema
def read(in: Seq[String]): Option[Data]
}
trait Schema1 extends Schema {
type D1
type FT1 <: FieldType { type Data = D1 }
type Schema = Tuple1[FT1]
type Data = Tuple1[D1]
def read(in: Seq[String]) = schema._1.parse(in(0)).map(Tuple1.apply)
}
trait Schema2 extends Schema {
type D1
type D2
type FT1 <: FieldType { type Data = D1 }
type FT2 <: FieldType { type Data = D2 }
type Schema = (FT1, FT2)
type Data = (D1, D2)
def read(in: Seq[String]) = {
for {
f <- schema._1.parse(in(0))
s <- schema._2.parse(in(1))
} yield (f, s)
}
}
我以为我可以使用这个系统来优雅地定义有意义的字段集,因为scala能够推断出类型成员:
class Person extends Schema2 {
val schema = (Name, Age)
}
但是,这不编译! 我必须包含所有类型成员的定义:
class Person extends Schema2 {
type D1 = String; type D2 = Int
type FT1 = Name.type; type FT2 = Age.type
val schema = (Name, Age)
}
scala怎么不能推断D1,...和FT1,...? 我怎样才能重构这个,所以我不必在Person
指定类型变量?
注意:一旦我对宏有了更好的理解,我计划将它们用于Schema
类型。 而且,我宁愿不使用无形。 这是一个很棒的图书馆,但我不想把它拉进来解决这个问题。
通过声明:
val schema: Schema
您指定该schema
必须是Schema
类型或其任何子类型 。 因此,了解schema
的类型,您无法推断Schema
因为它可能是schema.type
任何超类型 。
您可以通过完全颠倒事物来解决您的问题:根据schema.type
定义类型别名:
trait Schema2 extends Schema {
type Schema = (FieldType, FieldType)
type FT1 = schema._1.type
type FT2 = schema._2.type
type D1 = FT1#Data
type D2 = FT2#Data
type Data = (D1, D2)
def read(in: Seq[String]) = {
for {
f <- schema._1.parse(in(0))
s <- schema._2.parse(in(1))
} yield (f, s)
}
}
(不确定它是否真的有效,但理论上这应该是检查。)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.