Im wrestling with a problem with type inference for a definition that takes a mapped tuple as a parameter. Everything works fine when specifying the type, but having some trouble getting it to work without specifying them.
I would like to define some “capabilities”:
trait Usable[A]:
def apply[B](thunk: A ?=> B): B
trait Async extends Capability
object Async extends Usable[Async]:
given Usable[Async] = this
def apply[A](thunk: Async ?=> A): A =
given Async()
thunk
trait ResourceScope extends Capability
object ResourceScope extends Usable[ResourceScope]:
given Usable[ResourceScope] = this
def apply[A](thunk: ResourceScope ?=> A): A =
given ResourceScope()
thunk
Using a single one is fairly easy through the apply method, but would like to be able to specify multiple capabilities in a single ‘using’ clause.
type Using[T <: Tuple] = T match
case EmptyTuple => EmptyTuple
case a *: tail => Usable[a] *: Using[tail]
given [T <: Tuple] => Using[T] = ???
def using1[T <: Tuple](tuple: Tuple.Map[T, Usable]) = ???
def using2[T <: Tuple](tuple: Using[T]) = ???
def using3[T <: Tuple](using tuple: Using[T]) = ???
def using4[T <: Tuple : Tuple.IsMappedBy[Usable]](tuple: T): Unit = ???
calls to usingX type checks properly when including the type parameters, but type inference wont work here. Any suggestions on how to modify the signatures here, in order to aid the type inference? I guess using3 is the closest here, since you only have to specify everything once, but would prefer to use value parameters, as opposed to type parameters.
def test: Unit =
using1[(Async, ResourceScope)](Async, ResourceScope)
using2[(Async, ResourceScope)](Async, ResourceScope)
using3[(Async, ResourceScope)]
using4[(Usable[Async], Usable[ResourceScope])](Async, ResourceScope)
using1(Async, ResourceScope) // error
using2(Async, ResourceScope) // error
using4(Async, ResourceScope) // error