I'm trying to understand why I need to specify the specific enum type I'm using to be able to use the "match type" feature of scala 3.
val doesntCompile: String = testTypeMatch(FieldType.Text)
val compile: String = testTypeMatch[FieldType.Text.type](FieldType.Text)
def testTypeMatch[T <: FieldType](fieldType: T): Elem[T] =
fieldType match
case _: FieldType.Text.type => "randomString"
case _: FieldType.Number.type => 55
type Elem[x <: FieldType] = x match
case FieldType.Text.type => String
case FieldType.Number.type => Int
enum FieldType {
case Text
case Number
}
Without hardcoding [FieldType.Text.type] I'm getting a compilation error.
I've tried the same with sealed trait and it worked fine, specifying the type was not needed
sealed trait FieldType
object FieldType{
case object Text extends FieldType
case object Number extends FieldType
}
CodePudding user response:
The inferred type of FieldType.Text
is FieldType
, not FieldType.Text.type
.
Analogously, for the enum
enum Foo:
case Bar
the expression Foo.Bar
will have the type Foo
by default (try it out in the repl), similarly to how "hello"
has the type String
and not the singleton type "hello"
.
Demoting the FieldType
to a marker trait solves the issue:
val compilesAsExpected: String = testTypeMatch(Text)
def testTypeMatch[T <: FieldType](fieldType: T): Elem[T] =
fieldType match
case _: Text.type => "randomString"
case _: Number.type => 55
type Elem[x <: FieldType] = x match
case Text.type => String
case Number.type => Int
sealed trait FieldType
object Text extends FieldType
object Number extends FieldType
I must admit that I'm not so sure whether this is the most idiomatic way to do it, though; The enum
keyword was supposed to replace sealed trait
s, but this seems to be one of those cases where sealed trait
s behave quite differently from the enum
s.