Scala: “Static values” in traits?

烈酒焚心 提交于 2019-12-08 02:43:10

问题


Let's say I have:

trait X {
  val x: String
}

Using mix-in, I can define a trait such as

trait XPrinter {
  self: X =>
  def printX: String = "X is: " + x
}

such that a value/object implementing XPrinter implements x and give its methods such as printX access to the values specified in X such as x.

So far, so good.

I want to know if there is a way of having a trait in the form of:

trait XDependent[T <: X] {
  def printX: String = ???
}

So that XDependent instances have access to the value of T.x, with x assumed to be a "static value" glued with the type definition.

Now I understand why T.x can't be accessed in XDependent since a type subtyping X doesn't even have to implement the value of x and T.x might be abstract.

I understand that while Scala offers path-dependent types so that an abstract type defined in X can be used in XDependent, as shown here:

trait X {
  type Y //which can be constrained as desired.
}

trait XDependent[T <: X]{
  def foo(v:T#Y)
  def bar: T#Y
}

it doesn't offer the same thing with values as there is a clear separation between types and values in Scala.

Now I have come across the ideas of value-dependent types and literal-based types. I want to know if the idea of "static value for types", as illustrated above, has much overlap with the these concepts and what the connections are.

I'd also like to know about the different approaches taken in different languages, to blur the separation between types and values, how compatible they are with Scala's type system, and what the complications are in terms of integrating "static values" with the type-system. ie, (Can they be)/ (what happens if they are) overriden by a subtype, etc.


回答1:


If you can relax the requirement that XDependent has to be a trait, and make it an abstract class instead, then it seems as if a typeclass which provides a single null-ary method x is exactly what you want:

Here is your base trait X (without X.x or anything, that wouldn't be "static"):

trait X

Now you can define a typeclass HasStaticX[T] that guarantees that for a type T we can give some string x:

trait HasStaticX[T] {
  def x: String
}

Then you can use it like this:

abstract class XDependent[T <: X : HasStaticX] {
  def printX: String = implicitly[HasStaticX[T]].x
}

What HasStaticX does is essentially building a compile-time partial function that can take type T and produce a string-value x associated with T. So, in a way, it's something like a function that takes types and returns values. If this is what you want, then nothing has to be done to for "integrating static values", it just works in the current non-experimental mainstream versions of Scala.

The "value-dependent types" would be exactly the other way round: those would be essentially "functions" that assign types to values.



来源:https://stackoverflow.com/questions/50202845/scala-static-values-in-traits

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