The nomenclature of note here is path-dependent types. That's the option number 2 you talk of, and I'll speak only of it. Unless you happen to have a problem solved by it, you should always take option number 1.
What you miss is that the Parser
class makes reference to things defined in the Parsers
class. In fact, the Parser
class itself depends on what input
has been defined on Parsers
:
abstract class Parser[+T] extends (Input => ParseResult[T])
The type Input
is defined like this:
type Input = Reader[Elem]
And Elem
is abstract. Consider, for instance, RegexParsers
and TokenParsers
. The former defines Elem
as Char
, while the latter defines it as Token
. That means the Parser
for the each is different. More importantly, because Parser
is a subclass of Parsers
, the Scala compiler will make sure at compile time you aren't passing the RegexParsers
's Parser
to TokenParsers
or vice versa. As a matter of fact, you won't even be able to pass the Parser
of one instance of RegexParsers
to another instance of it.