Scala 书中的函数式编程:如何 运行 第 9 章中的内联示例?
Functional Programming in Scala book: How to run the inline examples from chapter 9?
我正在学习 Scala 函数式编程(Paul Chiusano 和 Rúnar Bjarnason 的 Manning 书)的第 9 章。本章中有内联示例,例如在练习 9.1 之后出现的以下示例:
char('a').many.slice.map(_.size) ** char('b').many1.slice.map(_.size)
到那时我已经实现了这些方法,我无法在 scala repl 中 运行 这个例子。可以找到代码 here.
我执行了以下操作来启动 repl:
./sbt
> ~exercises/console
scala> import fpinscala.parsing._
运行 只是 char('a')
给我以下错误:
scala> char('a')
<console>:18: error: not found: value char
char('a')
^
我是 scala 的新手,所以我可能错过了一些东西。我应该能够 运行 来自 repl 这样的特征的方法吗?如果是这样,我错过了什么?在其他章节中,我尝试尽快修改代码,以便了解概念并试验 API。但是,此时我无法 运行 最简单的内联示例。
类型参数Parser[+_]
几乎整章都是抽象的。只有在练习9.12中你应该尝试想出你自己的实现,并且只有在9.6.2中提供了一个可能的解决方案。
到那时,如果你想尝试为某种类型 A
:
生成 Parser[A]
的方法的实现,你有几种可能性
- 将它们直接添加到
Parsers
特征中。在那里,您可以使用所有其他方法,例如char
.
在所有可能的类型构造函数上参数化代码 Parser[+_]
,如 9.4 中的第 158 页所示。该部分以 "We don't have an implementation of our algebra yet" 的免责声明开始,但这不是必需的,因为实现被假定为稍后将提供的参数:
def jsonParser[Err, Parser[+_]](P: Parsers[Err, Parser]): Parser[JSON] = {
import P._ // now `char` is available.
???
}
此处适用于您的代码:
def myParser[P[+_]](P: Parsers[P]) = {
import P._
char('a').many.slice.map(_.size) **
char('b').many1.slice.map(_.size)
}
或者,通过另一个特征扩展 Parsers
,仍然保留 Parser[+_]
摘要:
trait MyParser[Parser[+_]] extends Parsers[Parser] {
def ab =
char('a').many.slice.map(_.size) **
char('b').many1.slice.map(_.size)
}
这是你自己的代码,有两个绝对编译的例子:
import language.higherKinds
import language.implicitConversions
trait Parsers[Parser[+_]] { self => // so inner classes may call methods of trait
def run[A](p: Parser[A])(input: String): Either[ParseError,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))
def char(c: Char): Parser[Char] =
string(c.toString) map (_.charAt(0))
def or[A](s1: Parser[A], s2: Parser[A]): Parser[A]
def listOfN[A](n: Int, p: Parser[A]): Parser[List[A]]
def many[A](p: Parser[A]): Parser[List[A]]
def slice[A](p: Parser[A]): Parser[String]
def many1[A](p: Parser[A]): Parser[List[A]] =
map2(p, many(p))(_ :: _)
def product[A,B](p: Parser[A], p2: Parser[B]): Parser[(A,B)]
def map[A,B](a: Parser[A])(f: A => B): Parser[B]
def map2[A,B,C](p: Parser[A], p2: Parser[B])(f: (A,B) => C): Parser[C] =
map(product(p, p2))(f.tupled)
def succeed[A](a: A): Parser[A] =
string("") map (_ => 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)
def many = self.many(p)
def map[B](f: A => B): Parser[B] = self.map(p)(f)
def slice: Parser[String] = self.slice(p)
def many1: Parser[List[A]] = self.many1(p)
def **[B](p2: => Parser[B]): Parser[(A,B)] =
self.product(p,p2)
def product[A,B](p: Parser[A], p2: Parser[B]): Parser[(A,B)] = self.product(p, p2)
def map2[A,B,C](p: Parser[A], p2: Parser[B])(f: (A,B) => C): Parser[C] = self.map2(p, p2)(f)
}
}
case class Location(input: String, offset: Int = 0) {
lazy val line = input.slice(0,offset+1).count(_ == '\n') + 1
lazy val col = input.slice(0,offset+1).reverse.indexOf('\n')
def toError(msg: String): ParseError =
ParseError(List((this, msg)))
def advanceBy(n: Int) = copy(offset = offset+n)
/* Returns the line corresponding to this location */
def currentLine: String =
if (input.length > 1) input.lines.drop(line-1).next
else ""
}
case class ParseError(stack: List[(Location,String)] = List(),
otherFailures: List[ParseError] = List()) {
}
object Parsers {
}
def myParser[P[+_]](P: Parsers[P]) = {
import P._
char('a').many.slice.map(_.size) **
char('b').many1.slice.map(_.size)
}
trait MyParser[P[+_]] extends Parsers[P] {
def ab =
char('a').many.slice.map(_.size) **
char('b').many1.slice.map(_.size)
}
请注意 ParserOps
已被修改:您在一些方法中有多余的参数 A
和 p
。
我正在学习 Scala 函数式编程(Paul Chiusano 和 Rúnar Bjarnason 的 Manning 书)的第 9 章。本章中有内联示例,例如在练习 9.1 之后出现的以下示例:
char('a').many.slice.map(_.size) ** char('b').many1.slice.map(_.size)
到那时我已经实现了这些方法,我无法在 scala repl 中 运行 这个例子。可以找到代码 here.
我执行了以下操作来启动 repl:
./sbt
> ~exercises/console
scala> import fpinscala.parsing._
运行 只是 char('a')
给我以下错误:
scala> char('a')
<console>:18: error: not found: value char
char('a')
^
我是 scala 的新手,所以我可能错过了一些东西。我应该能够 运行 来自 repl 这样的特征的方法吗?如果是这样,我错过了什么?在其他章节中,我尝试尽快修改代码,以便了解概念并试验 API。但是,此时我无法 运行 最简单的内联示例。
类型参数Parser[+_]
几乎整章都是抽象的。只有在练习9.12中你应该尝试想出你自己的实现,并且只有在9.6.2中提供了一个可能的解决方案。
到那时,如果你想尝试为某种类型 A
:
Parser[A]
的方法的实现,你有几种可能性
- 将它们直接添加到
Parsers
特征中。在那里,您可以使用所有其他方法,例如char
. 在所有可能的类型构造函数上参数化代码
Parser[+_]
,如 9.4 中的第 158 页所示。该部分以 "We don't have an implementation of our algebra yet" 的免责声明开始,但这不是必需的,因为实现被假定为稍后将提供的参数:def jsonParser[Err, Parser[+_]](P: Parsers[Err, Parser]): Parser[JSON] = { import P._ // now `char` is available. ??? }
此处适用于您的代码:
def myParser[P[+_]](P: Parsers[P]) = { import P._ char('a').many.slice.map(_.size) ** char('b').many1.slice.map(_.size) }
或者,通过另一个特征扩展
Parsers
,仍然保留Parser[+_]
摘要:trait MyParser[Parser[+_]] extends Parsers[Parser] { def ab = char('a').many.slice.map(_.size) ** char('b').many1.slice.map(_.size) }
这是你自己的代码,有两个绝对编译的例子:
import language.higherKinds
import language.implicitConversions
trait Parsers[Parser[+_]] { self => // so inner classes may call methods of trait
def run[A](p: Parser[A])(input: String): Either[ParseError,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))
def char(c: Char): Parser[Char] =
string(c.toString) map (_.charAt(0))
def or[A](s1: Parser[A], s2: Parser[A]): Parser[A]
def listOfN[A](n: Int, p: Parser[A]): Parser[List[A]]
def many[A](p: Parser[A]): Parser[List[A]]
def slice[A](p: Parser[A]): Parser[String]
def many1[A](p: Parser[A]): Parser[List[A]] =
map2(p, many(p))(_ :: _)
def product[A,B](p: Parser[A], p2: Parser[B]): Parser[(A,B)]
def map[A,B](a: Parser[A])(f: A => B): Parser[B]
def map2[A,B,C](p: Parser[A], p2: Parser[B])(f: (A,B) => C): Parser[C] =
map(product(p, p2))(f.tupled)
def succeed[A](a: A): Parser[A] =
string("") map (_ => 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)
def many = self.many(p)
def map[B](f: A => B): Parser[B] = self.map(p)(f)
def slice: Parser[String] = self.slice(p)
def many1: Parser[List[A]] = self.many1(p)
def **[B](p2: => Parser[B]): Parser[(A,B)] =
self.product(p,p2)
def product[A,B](p: Parser[A], p2: Parser[B]): Parser[(A,B)] = self.product(p, p2)
def map2[A,B,C](p: Parser[A], p2: Parser[B])(f: (A,B) => C): Parser[C] = self.map2(p, p2)(f)
}
}
case class Location(input: String, offset: Int = 0) {
lazy val line = input.slice(0,offset+1).count(_ == '\n') + 1
lazy val col = input.slice(0,offset+1).reverse.indexOf('\n')
def toError(msg: String): ParseError =
ParseError(List((this, msg)))
def advanceBy(n: Int) = copy(offset = offset+n)
/* Returns the line corresponding to this location */
def currentLine: String =
if (input.length > 1) input.lines.drop(line-1).next
else ""
}
case class ParseError(stack: List[(Location,String)] = List(),
otherFailures: List[ParseError] = List()) {
}
object Parsers {
}
def myParser[P[+_]](P: Parsers[P]) = {
import P._
char('a').many.slice.map(_.size) **
char('b').many1.slice.map(_.size)
}
trait MyParser[P[+_]] extends Parsers[P] {
def ab =
char('a').many.slice.map(_.size) **
char('b').many1.slice.map(_.size)
}
请注意 ParserOps
已被修改:您在一些方法中有多余的参数 A
和 p
。