|
| 1 | +trait Wrappable[T] { } |
| 2 | +given Wrappable[Float] { } |
| 3 | + |
| 4 | +case class Wrapped[T: Wrappable](value: T) |
| 5 | + |
| 6 | +trait Wrapper[T] { type WrappedT } |
| 7 | +object Wrapper { type Aux[T <: Tuple, WrappedT0 <: Tuple] = Wrapper[T] { type WrappedT = WrappedT0 } } |
| 8 | + |
| 9 | +given Wrapper[Unit] { type WrappedT = Unit } |
| 10 | + |
| 11 | +given [T: Wrappable]: Wrapper[T] { type WrappedT = Wrapped[T] } |
| 12 | + |
| 13 | +given [H: Wrappable, T <: Tuple, WrappedT0 <: Tuple](given Wrapper.Aux[T, WrappedT0]): Wrapper[H *: T] { |
| 14 | + type WrappedT = Wrapped[H] *: WrappedT0 |
| 15 | +} |
| 16 | + |
| 17 | +def wrappedFunction[F, FArgs <: Tuple, WrapperFArgs <: Tuple, R: Wrappable]( |
| 18 | + function: F |
| 19 | +)(input: FArgs)(given |
| 20 | + tf: TupledFunction[F, WrapperFArgs => Wrapped[R]], |
| 21 | + vs: Wrapper.Aux[FArgs, WrapperFArgs] |
| 22 | +): (R, R => Option[FArgs]) = { |
| 23 | + val variableInput = input.asInstanceOf[WrapperFArgs] // This is not correct but it's ok for the sake of this example. |
| 24 | + val result = tf.tupled(function)(variableInput) |
| 25 | + return (result.value, (_: R) => None) |
| 26 | +} |
| 27 | + |
| 28 | +object WrapperTest { |
| 29 | + def test1(x: Wrapped[Float], y: Wrapped[Float], z: Wrapped[Float]): Wrapped[Float] = { x } |
| 30 | + val test2: (Wrapped[Float], Wrapped[Float], Wrapped[Float]) => Wrapped[Float] = { (x, y, z) => x } |
| 31 | + |
| 32 | + def main(args: Array[String]): Unit = { |
| 33 | + wrappedFunction(test1: (Wrapped[Float], Wrapped[Float], Wrapped[Float]) => Wrapped[Float])(5f, 11f, 3f) |
| 34 | + wrappedFunction(test1)(5f, 11f, 3f) |
| 35 | + wrappedFunction(test2)(5f, 11f, 3f) |
| 36 | + } |
| 37 | +} |
0 commit comments