Generalized structural type conformance in Scala

泄露秘密 提交于 2019-11-29 22:13:20

问题


I'm interested in the problem of conforming a specific type to a more general structural type. Consider the following examples:

trait Sup

trait Sub extends Sup

type General = {
   def contra(o: Sub): Unit
   def co(): Sup
   def defaults(age: Int): Unit
   def defaults2(age: Int): Unit
   def defaults3(first: String): Unit
} 

trait Specific {
   def contra(o: Sup): Unit // doesn't conform
   def co(): Sub // conforms
   def defaults(age: Int, name: String = ""): Unit // doesn't conform
   def defaults2(name: String = "", age: Int = 0): Unit // doesn't conform
   def defaults3(first: String = "", last: String = ""): Unit // doesn't conform
}

In each of the non-conforming cases, a call to the method in General can safely be resolved to the corresponding method in Specific. A more interesting practical example can be found in this question:

trait Versionable[T] {
   self: { def copy(version: Int): T } =>
   val version = 0
   def incrementVersion = copy(version = version + 1)
}

case class Customer(name: String, override val version: Int) 
      extends Versionable[Customer] {
   def changeName(newName: String) = copy(name = newName)
}

Here, the Customer's copy method does not conform to the signature in Versionable's self-type annotation. Note, however, that if the compiler allowed, copy could be invoked just as it is in Versionable.incrementVersion. Clearly, the actual signature of Customer's copy method is too specific for use in Versionable, since it carries the irrelevant knowledge that one can optionally supply a name parameter.

Are there ways to work around these limitations? Are there reasons that such generalized conformance would be a bad idea?


回答1:


One concern is that when you read this code:

self: { def copy(version: Int): T }

you do not expect the name of the parameter to be significant, as it would have to be in this example:

case class Robot(number: Int, override val version: Int)
  extends Versionable[Robot]

EDIT: On another note, regarding the lack of parameter contravariance for methods, you can do:

type General = { val contra: (Sub => Unit) }
class B { val contra = ((o:Sup) => println(o)) }
var b:General = new B


来源:https://stackoverflow.com/questions/3471708/generalized-structural-type-conformance-in-scala

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!