Читая Функциональное программирование на Scala Кьюзано и Бьярнасон, я обнаружил следующий код в главе 9, Комбинаторы синтаксического анализатора:
trait Parsers[ParseError, Parser[+_]] { self =>
...
def or[A](s1: Parser[A], s2: Parser[A]): Parser[A]
implicit def string(s: String): Parser[String]
implicit def operators[A](p: Parser[A]) = ParserOps[A](p)
implicit def asStringParser[A](a: A)(implicit f: A => Parser[String]):
ParserOps[String] = ParserOps(f(a))
case class ParserOps[A](p: Parser[A]) {
def |[B>:A](p2: Parser[B]): Parser[B] = self.or(p,p2)
def or[B>:A](p2: => Parser[B]): Parser[B] = self.or(p,p2)
}
}
Я понимаю, что в случае несовместимости типов или отсутствия параметров во время компиляции компилятор Scala будет искать недостающую функцию, которая преобразует несоответствующий тип в желаемый тип или переменную в области видимости с желаемым типом, который соответствует отсутствующему параметру соответственно. .
Если строка встречается там, где требуется Parser[String]
, должна быть вызвана строковая функция в приведенном выше трейте для преобразования строки в Parser[String]
.
Однако мне сложно понять функции operators
и asStringParser
. Вот вопросы, которые у меня есть:
- Почему для функции неявных операторов нет возвращаемого типа?
- Почему ParserOps определен как
case class
и почему функция|
илиor
не может быть определена в самом типе Parsers? - Чего именно
asStringParser
пытается достичь? Какова его цель здесь? - Зачем нужен
self
? В книге говорится: «Используйте self, чтобы явно исключить неоднозначность ссылки на метод or в этой характеристике», но что это означает?
Мне действительно нравится книга, но использование в этой главе сложных языковых конструкций препятствует моему прогрессу. Было бы очень полезно, если бы вы объяснили мне, как работает этот код. Я понимаю, что цель состоит в том, чтобы сделать библиотеку «удобнее» для использования с помощью таких операторов, как |
и or
, но не понимаю, как это делается.
or
вParsers
, а не вParserOps
. - person Jörg W Mittag   schedule 13.04.2018