Question

I'm trying to implement/override a function with an empty input argument by using partial function. It is best explained by this non-working minimal example:

trait T
trait TFactory {
  def build(): T
}

class A(someParameter: Int) extends T

object A extends TFactory {
  def build(someParameter: Int)(): T = new A(someParameter)
}

The compiler complains: object creation impossible, since method build in trait TFactory of type ()T is not defined, which makes sense, since the type of build is (Int)()T. My next idea was to make the type of build explicitly to a function taking an empty argument and returning a T, i.e.:

trait T 
trait TFactory {
  def build: () => T    // what about empty parenthesis after build?
}

class A(someParameter: Int) extends T 

object A extends TFactory {
  def build(someParameter: Int): (() => T) = (() => new A(someParameter))
}

Now it is obvious that the type of build is () => T. To my surprise the compiler now complains about object creation impossible, since method build in trait TFactory of type => () => T is not defined (note the type suddenly starts with a =>). Desperately adding empty parenthesis at the end of the function definition(s) does not help either.

How can I convince my compiler that these types actually are the same?

Clarification:

My primary goal is to achieve a parameter-free initialization of T without the need of a factory for factories. Example:

val t = A(33).build()      // if this is possible, I though it might be possible to have:
val t = A.build(33)()

Conclusion:

I think it is just not possible, because the abstract function simply determines how many argument blocks the build function must take. In other words: You cannot by implemented an abstract function by a function, whose partial application happens to have the same signature as the function you are trying to implement.

Was it helpful?

Solution

I not exactly sure what you want to achieve. Let's say your TFactory was given as in your first example:

trait T

trait TFactory {
  def build(): T
}

Then the build method obviously cannot take any parameter. If you want to configure your factory, you can have a factory-factory:

class A(x: Int) extends T

object A {
  def apply(x: Int): TFactory = new TFactory {
    def build() = new A(x)
  }
}

val factory = A(33)
val t = factory.build()

If you define TFactory simply to be a function from () to T, you can use currying

type TFactory = () => T

object A {
  def apply(x: Int)(): T = new A(x)
}

val factory: TFactory = A(33) _
val t = factory()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top