Dependent typing on lazy argument (Scala 3)

Hello!

I tried Match Types for dependent typing in function with lazy argument. And its value was computed at runtime. Is this the expected behavior?

Scastie example: Scastie - An interactive playground for Scala

I thought that type checking is done at compile time. Is there a way to do dependent typing with the preservation of argument laziness in Scala 3?

1 Like

I’m not sure what exactly you’re trying to do, but the reason test runs its block and plain doesn’t, has nothing to do with its return type.

In plain, you just return a string and don’t use t. But in test:

def test[T](t: => T): Construct[T] =
  t match
    case _: Any => "not used"

you match on t, which causes it to be evaluated. A by-name parameter is evaluated when it is used, and matching on it uses it, even when the only case ignores its value.

I’m trying to compute return type of function test without its argument evaluation.

A more meaningful example: Scastie - An interactive playground for Scala

I hoped that match expression for match types works at compile-time only and doesn’t affect variables at runtime. I know that it can be done with dependent methods and implicit machinery, but match types looks like a more elegant solution.

And I don’t understand why value of argument is computed if match clause checks only type known at compile time.

A match is a runtime expression, it is evaluated at runtime.

In your case how would you expect it to pick the correct branch to execute? At ru time due type erasure Input is nothing more than Object

Ok, looks like I incorrectly understand documentation about “special mode of typing for match expressions”. Thank you for replies.

Uhm, maybe with inline it would work?

I mean, at some point the compiler knows the correct type of the expression, so maybe it could online the match

Maybe even is just an oversight from the maintainers in reference to by-name parameters.

If you want a “compile time” match on the type you can do this:

import scala.compiletime.erasedValue

inline def test[T](t: => T): Construct[T] =
  inline erasedValue[T] match
    case _: Any => "not used"

I solved it with summonFrom and transparent inline: Scastie - An interactive playground for Scala

Looks verbose but still better than Scala 2 :slight_smile:

2 Likes

That actually looks like a great use case for an inline match with erasedValue. At least if that match type works for you. And even without the match type you could probably use transparent.