4

I want to have a class which takes a parameter with a class-dependent type, as I've often done for methods. However, to my surprise, this didn't work:

scala> trait Compiler { trait Config }
defined trait Compiler

// works fine, as expected
scala> def f(c: Compiler)(conf: c.Config) = {}
f: (c: Compiler)(conf: c.Config)Unit

scala> class F(val c: Compiler)(val conf: c.Config)
<console>:8: error: not found: value c
       class F(val c: Compiler)(val conf: c.Config)
                                          ^

Why? And are there any workarounds?

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • I got the following **without currying**: `:11: error: illegal dependent method type: parameter appears in the type of another parameter in the same section or an earlier one class F(val c: Compiler, val conf: c.Config) ^` – Kevin Meredith Sep 24 '15 at 14:26
  • 1
    @KevinMeredith The error without currying is expected (it's the same for methods) and seems clear enough to me, even if I would prefer it worked. – Alexey Romanov Sep 24 '15 at 14:31

2 Answers2

5

A workaround which seems acceptable (can't create an invalid F without additional casts):

class F private (val c: Compiler)(_conf: Compiler#Config) {
  def conf = _conf.asInstanceOf[c.Config]
}

object F {
  def apply(c: Compiler)(conf: c.Config) = new F(c)(conf)
}
Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
2

As to why path-dependent types do not work in a class primary constructor the answer is given in section 5.3 of the Scala language specification:

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

(though it seems that "members of the class template" means only the members defined within the constructor parameter sections).

But a class may have additional constructors that make it possible to write a workaround that does not need additional casts and objects:

class F private (val conf: Compiler#Config, val c: Compiler) {
    def this(c: Compiler)(conf: c.Config) = this(conf, c)
}
Max Plevako
  • 1,832
  • 11
  • 11