Open
Description
- Scala:
3.X
- scala-parser-combinators:
2.1.1
Consider the following motivating example:
import scala.util.parsing.combinator.Parsers
enum Token {
case A()
case B()
case C()
}
object Parser extends Parsers {
override type Elem = Token
def tokenA: Parser[Token.A] = ???
def tokenB: Parser[Token.B] = ???
def tokenC: Parser[Token.C] = ???
def tokenABC: Parser[Token.A | Token.B | Token.C] =
tokenA | tokenB | tokenC // error
}
Unfortunately the definition tokenABC
doesn't compile:
Found: Parser[Token]
Required: Parser[Token.A | Token.B | Token.C]
tokenA | tokenB | tokenC
A workaround is to ascribe tokenA
to the desired union type:
def tokenABC: Parser[Token.A | Token.B | Token.C] =
(tokenA: Parser[Token.A | Token.B | Token.C]) | tokenB | tokenC
However this looks unnatural and arguably not very intuitive.
If we look at the source, this is how the choice operator is defined:
def | [U >: T](q: => Parser[U]): Parser[U]
And it is now evident why the code in the above example fails to compile. The obvious change would be to update the signature to:
def | [U](q: => Parser[U]): Parser[T | U]
Which would definitely break cross compatibility and therefore wouldn't be a viable solution.
Metadata
Metadata
Assignees
Labels
No labels