对于自定义DSL,我有一组数据生产者和消费者。 (它实际上比这复杂一点,但这足以设置问题。)用户设置一个消费者,这可能需要某种类型的数据。我想确保类型系统强制将正确类型的数据发送给正确的消费者。
数据的可能详细说明是有限的,因为可以编写一个至少可以填写合理默认值的单个数据生成器。因此,对于由默认数据供应商组成的所有数据类型应该存在下限。此外,所有数据都具有某些特征,因此应该有一个上限。数据可以通过保持特定消费者适用性的方式进行操作,或者扩大对更多消费者的适用性。因此,类型应该类似于
AllData <: D <: AnyData
在Scala中编码此约束的最简单且最优雅的方法是什么,假设我实际上并不想要AllData
扩展所有其他数据类型D
?
现在我只有一个看起来像
的超类class AnyData {
def foo: Int => String = defaultIntToStringImpl
def mapFoo(oo: String => String) = AllData((foo _) andThen oo)
}
和子类可以覆盖它
class LiteralNumberData extends AnyData {
override val foo = (i: Int) => i.toString
}
并且有一个案例类允许每个方法都可插入
case class AllData(override val foo: Int => String) {}
但是,如果消费者要允许映射,那么消费者真的只能在AnyData
和AllData
之间进行选择,因为映射都会以AllData
结尾。这对消费者来说并不像我想的那样提供那么多安全,而且我要确保记得不要做任何事情。 LiteralNumberData
无法打包到AllData
。
答案 0 :(得分:2)
我会对类型进行约束,如下所示:
trait ProdConsConstraint[Producer,Consumer]{
type Output <: AnyData
}
如果我正确地跟着你。然后,您可以使用依赖类型来强制您正在使用的类型的适用性。
def foo(prod: Producer, con: Consumer)(implicit ev:ProdConsConstraint[Producer,Consuer]): ev.Output = ???
这样就不需要下限了,同时也允许你有空间来打开&#34;打开&#34;通过隐式参数的范围确定。
嗯......听起来太复杂了。也许我不能充分理解这个问题。