Scala 抽象路径依赖类型问题第 2 部分
关于 Scala 抽象类型的几个问题。
- 如果我想在构造函数值中使用该类型,是否必须使用参数化 [] 类型? IE。是否可以有一个具有抽象构造函数参数类型的类?如果我摆脱 [T1,T2] 并使用 INode#TKey 和 INode#TValue 作为构造函数参数类型,我在做什么?我收到令人困惑的错误消息。
- 如何在不诉诸内部类型的情况下很好地解决这个问题?我在定义中使用 INode 似乎意味着我可以返回/接收具有不同类型的 TKey 和 INode。 T值。如何将其限制为与当前类型相同的 TKey/TValue 类型,而不限制自己返回/接收确切的“this”实例?
trait AbsTypes
{
type TKey
type TValue
}
trait INode extends AbsTypes
{
def get(key : TKey) : TValue
def set(key : TKey, v : TValue) : INode
def combine(other : INode, key : TKey): INode
}
class ANode[T1,T2](
val akey : T1,
val aval : T2
) extends INode
{
type TKey = T1
type TValue = T2
type Node = ANode[T1,T2]
def get(key : TKey) : TValue = { aval }
def set(key : TKey, v : TValue) : INode = {
new ANode(key,v)
}
def combine(other : INode, key :TKey) : INode = {
//ERROR : type mismatch; found : key.type (with underlying type ANode.this.TKey) required: other.TKey
other.set(key, aval)
}
}
Couple of questions on scala abstract types.
- Do I have to use parameterized [] types if I want to use the type in a constructor value? ie. is it possible to have a class with abstract constructor parameter types? If I get rid of [T1,T2] and use INode#TKey and INode#TValue as the constructor parameter types, what am I doing? I get confusing error messages.
- How do I solve this nicely without resorting to inner types? My use of INode in the definitions seem to be implying I could return / receive an INode with different types for TKey & TValue. How do I restrict it to the same TKey/TValue types as my current type, without restricting myself to returning/receiving exactly "this" instance?
trait AbsTypes
{
type TKey
type TValue
}
trait INode extends AbsTypes
{
def get(key : TKey) : TValue
def set(key : TKey, v : TValue) : INode
def combine(other : INode, key : TKey): INode
}
class ANode[T1,T2](
val akey : T1,
val aval : T2
) extends INode
{
type TKey = T1
type TValue = T2
type Node = ANode[T1,T2]
def get(key : TKey) : TValue = { aval }
def set(key : TKey, v : TValue) : INode = {
new ANode(key,v)
}
def combine(other : INode, key :TKey) : INode = {
//ERROR : type mismatch; found : key.type (with underlying type ANode.this.TKey) required: other.TKey
other.set(key, aval)
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为参数化类型非常适合您的设置。抽象类型绑定到特定实例,因此您会收到错误。我承认我没有尝试重构您的示例以使抽象类型起作用,但以下代码片段不会尝试混合抽象类型和参数化类型,并且 scalac 对此没有任何问题。
I think parameterized types fit nicely in your setting. Abstract types are bound to a particular instance, hence the error you are getting. I confess I didn't try to refactor your example to make abstract types work, but the following snippet doesn't try to mix abstract and parameterized types, and scalac has no problems with it.
首先我想指出,
combine
方法根本不使用other
参数,你也可以写:..但我猜它是这就是我们所追求的原则。
如果您有一个非常小的允许的 TKey 和 TValue 组合集(比如 2),您可以使用抽象类型策略并从代码中删除参数化类型:
在我的示例中,您将在 < 的方法中得到一些代码重复code>StringNode 和
IntNode
,但至少说明了抽象类型的原理。First of all I would like to point out that the
combine
method does not use theother
parameter at all, you could just as well write:.. but I guess it is just the principle we are after here.
If you have a very small set of allowed TKey and TValue combinations (say 2), you can use the abstract type tactics and cut parameterized types out of the code all together:
In my example you will get some code duplication in the methods of
StringNode
and, say,IntNode
, but at least the principle of abstract types is illustrated.由于
other
是不同的INode
,因此它有自己的TKey
和TValue
类型。无法保证此ANode
的TKey
和TValue
与other
的相匹配。您需要使用相等或下限(我使用的)来约束类型。我没有尝试运行它,但以下代码针对 Scala 2.8.0 进行编译Since
other
is a differentINode
, it has it's ownTKey
andTValue
types. There is no guarantee thatTKey
andTValue
of thisANode
match those ofother
. You need to constrain the types with either equality or lower bound (which I used). I didn't try to run it, but the following compiles against Scala 2.8.0感谢您的回答,他们是最有帮助的&确实帮助了我的理解。
我发现的一种替代解决方案如下。 AbsType 不需要是基类,您可以使用它来包装参数化类型定义。
Thanks for your answers, they're most helpful & have really helped my understanding.
One alternative solution I've found is below. The AbsType doesn't need to be the base class, you can use it to wrap up the parameterized type definitions.