0

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.

tshepang
  • 12,111
  • 21
  • 91
  • 136
bluenote10
  • 23,414
  • 14
  • 122
  • 178
  • I'm not sure I follow. TFactory promises to provide a method "build" that takes no parameters and returns either a T (in the first example) or a function returning T (in the second). But no such method is defined in object A. – Matt Malone Dec 11 '13 at 15:47
  • The intended behavior of `build` is to take nothing as input and return a new instance of `T`. The intention behind the implementation in `object A` is simply to wrap all necessary parameters of `A` allowing a "parameter-free" initialization. – bluenote10 Dec 11 '13 at 15:51

1 Answers1

1

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()
0__
  • 66,707
  • 21
  • 171
  • 266
  • And shouldn't it be possible to achieve exactly the same by currying the `build` function? After all, my primary goal indeed was to avoid a FactoryFactory. I was hoping to achieve this parameter-free initialization simply by returning a function of the type `() => T`, which seems to be possible since the types in the examples are "almost right". – bluenote10 Dec 11 '13 at 15:54
  • Thanks for the suggestion! I think my main problem with this solution is that I cannot enforce that everyone who implements `T` should also provide a parameter-free way to instantiate a `T`. My original goal was to have a `val factory: TFactory` within `T`, which would have enforced this link (sorry that I failed to make that clear enough). – bluenote10 Dec 11 '13 at 16:51
  • For sake of completeness: I asked a new question [here](http://stackoverflow.com/q/20542997/1804173) which deals with the big picture behind this question; Or in other words: This question here was simply a completely misguided attempt to come up with an alternative solution to that other question. I've added a corresponding conclusion above and accept this answer, unless anybody will prove that my conclusion is wrong. – bluenote10 Dec 12 '13 at 13:44