Generate functions based on type parameter

2019-07-08 20:10发布

问题:

I would like to generate functions for a class accepting 1 type parameter, which wraps a by name value.

class C[T](_t: => T) {
    def t: T = _t
}

The functions I would like to generate are derived by the functions available on T.

What I would like exactly, is to get all the functions available for T, change their contract and implementation in a programmatic way, and make them available for C.

  • By changing their contract, I mean changing their signature so they return C[R], where R stands for the return type of the original function.

  • By changing their implementation, I mean wrapping the result inside C before returning it.

eg.

def +(that: Int): Int =
    this + that

would become available on C[Int] as

def +(that: Int): C[Int] =
    C(this.t + that)

This would be done in order to remove the boilerplate of having to wrap inside C a computation in order to keep it non-evaluated.

eg.

val c1 = new C(1)

val c2: C[Int] = C(c1.t + 1)
c2.t == 2

would be able to be expressed also as

val c2: C[Int] = c1 + 1
c2.t == 2

How can I achieve this by using Scala 2 or dotty macros? Or, can this be achieved in another way?

回答1:

Try to add one more implicit conversion additionally to advised by @KrzysztofAtłasik in your previous question.

implicit def conversion[T](c: C[T]): T = c.t
implicit def conversion1[T](t: => T): C[T] = new C(t)

Or make class implicit

implicit class C[T](_t: => T) {
  def t: T = _t
}

Regarding macros, since you want to add definitions you would need macro annotations rather than def macros. Dotty doesn't have macro annotations, it has only inline macros like Scala 2 def macros.

And macro annotations don't help either. When you define class C[T] it's not known what T is (this will be known only at call site), so it's not known what methods to add.

Dotty has implicit conversions too

given [T] as Conversion[T, C[T]] = new C(_)
given [T] as Conversion[C[T], T] = _.t

(currently it's given, formerly it was implicit, then implied, then delegate, currently in 0.17 given, this can change again).

It seems Conversion[(=> T), C[T]] is not allowed.