Dependent types not working for constructors?

前端 未结 1 622
滥情空心
滥情空心 2020-12-30 06:40

Path-dependent types are useful:

trait Sys {
  type Global
}
def foo[S <: Sys](system: S)(global: system.Global) = ()

Why doesn\'t this

相关标签:
1条回答
  • 2020-12-30 07:35

    This seems like a bug to me. Edit: found it, this is SI-5712.

    Section §5.3 of the 2.9 SLS says:

    (ps1 ) . . . (psn ) are formal value parameter clauses for the primary constructor of the class. The scope of a formal value parameter includes all subsequent parameter sections and the template t .

    There is an exception:

    However, a formal value parameter may not form part of the types of any of the parent classes or members of the class template t .

    But it says it cannot be part of the types of any of the parent classes or members, not of any of the following parameter sections, so it does not seems to forbid path-dependent types between argument groups.

    You can go around this with a secondary constructor:

    class Foo[S <: Sys] private[this] () {
      def this(system: S)(global: system.Global) = this
    }
    

    Edit: this secondary constructor workaround is not very good: exposing system or global become very difficult because only the primary constructor can declare vals.

    An example with a cast:

    class Foo[S <: Sys] private[this] () {
      private[this] var _system: S = _
      private[this] var _global: system.Global = _
    
      def this(system0: S)(global0: system0.Global) = {
        this
        _system = system0
        _global = global0.asInstanceOf[system.Global]
      }
    
      lazy val global: system.Global = _global
      lazy val system: S = _system
    }
    

    But this is getting awful. @senia's suggestion is much better.

    0 讨论(0)
提交回复
热议问题