Hey!
I have the following code:
type Size = "single" | "optional" | "many"
type Out[S <: Size, A] =
S match
case "single" => A
case "optional" => Option[A]
case "many" => List[A]
trait Runner[S <: Size, A]:
def input: A
inline def run: Out[S, A] =
inline erasedValue[S] match
case _: "single" =>
mkSingle(input)
case _: "optional" =>
mkOption(input)
case _: "many" =>
mkList(input)
It works awesome and user of the Runner trait always gets the output type they need.
All above mk-functions accept the same type A and everything works fine. But now I change their signature and want for example that mkSingle accepted Boolean and thus my A becomes Boolean if and only if the S is “single”:
type MkInput[S <: Size, A] =
S match
case "single" => Boolean
case "optional" => A
case "many" => String
trait Runner[S <: Size, A]:
inline def run(input: MkInput[S, A]): Out[S, A] =
inline erasedValue[S] match
case _: "single" =>
mkSingle(input) // Now all mk-functions are different now
case _: "optional" =>
mkOption(input)
case _: "many" =>
mkList(input)
This code doesn’t however, although I expect it should - the S type is shared between MkInput and Out, hence we always know upfront that mkSingle or mkOption gets the expected type. However I’m getting the following error, indicating that match types are not expanded on argument position:
[error] 132 | mkOption(input)
[error] | ^^^^^
[error] |Found: (input : io.foldables.ratio.queries.Action.MkInput[S, A])
[error] |Required: Boolean
[error] |
[error] |where: S is a type in method foo with bounds <: io.foldables.ratio.queries.Action.Size
Is there a way to proove the compiler that my input is of proper type?