I'm learning Scala 3, and I was intrigued by match types and literal types.
I'd like to write a function that takes one of a few literal types, and returns a particular type as a function of which literal type was passed in.
Here's a fairly minimal example of what I'm trying to do:
type TestMatchType[T] = T match
case "String1" => Int
case "String2" => String
def testMatchType[T](input: T): TestMatchType[T] =
input match
case "String1": "String1" => 1
case "String2": "String2" => "Two"
val string1Output: Int = testMatchType("String1")
In words:
- "I'd like to write a function,
testMatchType, which takes an argument whose type is either the type literal"String1", or the type literal"String2". If an argument with type"String1"is passed, the function should return anInt. If an argument with type"String2"is passed, the function should return aString. If an argument is passed whose type is not one of these type literals, a compile-time error is produced."
However, when I try to compile the above code, I get the following error:
1 |val string1Output: Int = testMatchType("String1")
| ^^^^^^^^^^^^^^^^^^^^^^^^
| Found: TestMatchType[String]
| Required: Int
|
| Note: a match type could not be fully reduced:
|
| trying to reduce TestMatchType[String]
| failed since selector String
| does not match case ("String1" : String) => Int
| and cannot be shown to be disjoint from it either.
| Therefore, reduction cannot advance to the remaining case
|
| case ("String2" : String) => String
I'm trying to grok that error message. I'm struggling to understand the line "selector String does not match case ("String1" : String) => Int". I would love some advice if there's a way to make this work.
Thank you!
You don't need to use
"foo": "foo", just use_: "foo".However, the error happens because
Twill not be inferred as a singleton type, so the return type will never beIntorStringeither, it'll remainTestMatchType[String]. You'll either have to useT <: Singletonor useinput.typeas an argument toTestMatchType(I prefer the latter).Scastie