Scala & for comprehensions:将 map、flatmap 和 filter 作为依赖于伴随对象的实例方法实现时会出现编译错误
Scala & for comprehensions: Compile errors when implementing map, flatmap, and filter as instance methods that rely on a companion object
对于任何有问题的 synax,我提前表示歉意。我正在学习一门新语言,非常感谢您的帮助!
出于学习的目的,我正在尝试设置一个自定义列表实现(名为 Mlist,用于 'my list'),它可以与 Scala 的理解一起使用。在尝试这样做时,我 运行 遇到了一个让我难过的编译错误。
这是有问题的代码:
sealed trait Mlist[+A] {
def map[A,B](f: A => B): Mlist[B]
def flatMap[A,B](f: A => Mlist[B]): Mlist[B]
def filter[A](f: A => Boolean): Mlist[A]
}
case object Mnil extends Mlist[Nothing] {
def map[A,B](f: A => B): Mlist[B] = {
Mnil
}
def flatMap[A, B](f: A => Mlist[B]): Mlist[B] = {
Mnil
}
def filter[A](f: A => Boolean): Mlist[A] = {
Mnil
}
}
case class Mcons[+A](head: A, tail: Mlist[A]) extends Mlist[A] {
def map[A,B](f: A => B): Mlist[B] = {
Mlist.map(this)(f)
}
def flatMap[A,B](f: A => Mlist[B]): Mlist[B] = {
Mlist.flatMap(this)(f)
}
def filter[A](f: A => Boolean): Mlist[A] = {
Mlist.filter(this)(f)
}
}
object Mlist {
def map[A,B](l: Mlist[A])(f: A => B): Mlist[B] = {
foldRight(l, Mnil: Mlist[B])((h, t) => Mcons(f(h), t))
}
def filter[A](as: Mlist[A])(f: A => Boolean): Mlist[A] = {
foldRight(as, Mnil: Mlist[A])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
}
def flatMap[A, B](as: Mlist[A])(f: A => Mlist[B]): Mlist[B] = {
concat(map(as)(f))
}
}
object Mlist {
def map[A,B](l: Mlist[A])(f: A => B): Mlist[B] = {
foldRight(l, Mnil: Mlist[B])((h, t) => Mcons(f(h), t))
}
def filter[A](as: Mlist[A])(f: A => Boolean): Mlist[A] = {
foldRight(as, Mnil: Mlist[A])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
}
def flatMap[A, B](as: Mlist[A])(f: A => Mlist[B]): Mlist[B] = {
concat(map(as)(f))
}
}
基本思想是有一个trait来定义我的两个Mlist实现的方法类。我没有为 map 之类的东西重新实现实例方法,而是尝试调用我的帮助程序对象以重用它的方法。
这是我看到的编译错误:
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:31: type mismatch;
[error] found : A(in method map) => B
[error] required: A(in class Mcons) => B
[error] Mlist.map(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:35: type mismatch;
[error] found : A(in method flatMap) => Mlist[B]
[error] required: A(in class Mcons) => Mlist[B]
[error] Mlist.flatMap(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:39: type mismatch;
[error] found : A(in method filter) => Boolean
[error] required: A(in class Mcons) => Boolean
[error] Mlist.filter(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:39: type mismatch;
[error] found : Mlist[A(in class Mcons)]
[error] required: Mlist[A(in method filter)]
[error] Mlist.filter(this)(f)
而且,如果它真的有用,下面是我最终打算实现的(未经测试且可能完全功能失调的)理解:
def combos(list: Mlist[A]): Mlist[Mlist[A]] = {
for {
el <- list
combo <- combos(tail(list))
} yield {
setHead(el, combo)
}
}
任何人都可以告诉我我的编译错误是什么意思以及如何解决它们吗?
您正在使用 Mlist.map
、Mlist.flatMap
和 [=20] 中的同名类型参数隐藏 Mlist
特征中定义的类型参数 A
=] 方法:
sealed trait Mlist[+A] {
// ↑
// this is a type parameter named `A`
def map[A,B](f: A => B): Mlist[B]
// ↑
// this is a completely different, totally unrelated type parameter,
// confusingly also named `A`
def flatMap[A,B](f: A => Mlist[B]): Mlist[B]
def filter[A](f: A => Boolean): Mlist[A]
}
Scala 在错误消息中告诉您这一点,它在同名 A
s 和 which 参数名称后的括号中告诉您=22=]它在谈论:
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:31: type mismatch;
[error] found : A(in method map) => B
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] required: A(in class Mcons) => B
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] Mlist.map(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:35: type mismatch;
[error] found : A(in method flatMap) => Mlist[B]
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] required: A(in class Mcons) => Mlist[B]
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] Mlist.flatMap(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:39: type mismatch;
[error] found : A(in method filter) => Boolean
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] required: A(in class Mcons) => Boolean
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] Mlist.filter(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:39: type mismatch;
[error] found : Mlist[A(in class Mcons)]
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] required: Mlist[A(in method filter)]
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] Mlist.filter(this)(f)
也许,如果您在所有地方都使用新名称并且不隐藏任何内容,错误消息可能会变得更清楚:
sealed trait Mlist[+A] {
def map[B, C](f: B => C): Mlist[C]
def flatMap[D, E](f: D => Mlist[E]): Mlist[E]
def filter[F](f: F => Boolean): Mlist[F]
}
case object Mnil extends Mlist[Nothing] {
def map[G, H](f: G => H): Mlist[H] = this
def flatMap[I, J](f: I => Mlist[J]): Mlist[J] = this
def filter[K](f: K => Boolean): Mlist[K] = this
}
case class Mcons[+L](head: L, tail: Mlist[L]) extends Mlist[L] {
def map[M, N](f: M => N): Mlist[N] = Mlist.map(this)(f)
def flatMap[O, P](f: O => Mlist[P]): Mlist[P] = Mlist.flatMap(this)(f)
def filter[Q](f: Q => Boolean): Mlist[Q] = Mlist.filter(this)(f)
}
object Mlist {
def map[R, S](l: Mlist[R])(f: R => S): Mlist[S] =
foldRight(l, Mnil: Mlist[S])((h, t) => Mcons(f(h), t))
def filter[T](as: Mlist[T])(f: T => Boolean): Mlist[T] =
foldRight(as, Mnil: Mlist[T])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
def flatMap[U, V](as: Mlist[U])(f: U => Mlist[V]): Mlist[V] =
concat(map(as)(f))
}
这给出了以下错误消息:
<console>:24: error: type mismatch;
found : M => N
required: L => N
def map[M, N](f: M => N): Mlist[N] = Mlist.map(this)(f)
^
<console>:25: error: type mismatch;
found : O => Mlist[P]
required: L => Mlist[P]
def flatMap[O, P](f: O => Mlist[P]): Mlist[P] = Mlist.flatMap(this)(f)
^
<console>:26: error: type mismatch;
found : Q => Boolean
required: L => Boolean
def filter[Q](f: Q => Boolean): Mlist[Q] = Mlist.filter(this)(f)
^
<console>:26: error: type mismatch;
found : Mlist[L]
required: Mlist[Q]
def filter[Q](f: Q => Boolean): Mlist[Q] = Mlist.filter(this)(f)
^
我希望现在可以清楚地看到您的错误来自何处。
请注意,您实际上从未在任何地方使用特征或 class 的类型参数,您 总是 仅使用方法的类型参数。这肯定听起来很可疑;您需要实际使用这些类型参数!
sealed trait Mlist[+A] {
def map[B](f: A => B): Mlist[B]
def flatMap[B](f: A => Mlist[B]): Mlist[B]
def filter(f: A => Boolean): Mlist[A]
}
case object Mnil extends Mlist[Nothing] {
def map[A, B](f: A => B): Mlist[B] = this
def flatMap[A, B](f: A => Mlist[B]): Mlist[B] = this
def filter[A](f: A => Boolean): Mlist[A] = this
}
case class Mcons[+A](head: A, tail: Mlist[A]) extends Mlist[A] {
def map[B](f: A => B): Mlist[B] = Mlist.map(this)(f)
def flatMap[B](f: A => Mlist[B]): Mlist[B] = Mlist.flatMap(this)(f)
def filter(f: A => Boolean): Mlist[A] = Mlist.filter(this)(f)
}
object Mlist {
def map[A, B](l: Mlist[A])(f: A => B): Mlist[B] =
foldRight(l, Mnil: Mlist[B])((h, t) => Mcons(f(h), t))
def filter[A](as: Mlist[A])(f: A => Boolean): Mlist[A] =
foldRight(as, Mnil: Mlist[A])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
def flatMap[A, B](as: Mlist[A])(f: A => Mlist[B]): Mlist[B] =
concat(map(as)(f))
}
顺便说一句,我认为你的抽象是错误的方式:当然,外部对象如 Mlist
单例对象应该 不 知道内部Mcons
个对象并操纵它们!一个对象应该知道如何操纵自己,而其他人不应该知道这一点。事实上,您的抽象奇怪地混合在一起:Mnil
知道如何处理自身,但 Mcons
对象不知道。这样看起来更清醒:
case class Mcons[+A](head: A, tail: Mlist[A]) extends Mlist[A] {
def map[B](f: A => B): Mlist[B] = foldRight(Mnil: Mlist[B])((h, t) => Mcons(f(h), t))
def flatMap[B](f: A => Mlist[B]): Mlist[B] = concat(map(f))
def filter(f: A => Boolean): Mlist[A] =
foldRight(Mnil: Mlist[A])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
}
object Mlist {
def map[A, B](l: Mlist[A])(f: A => B): Mlist[B] = l map f
def filter[A](as: Mlist[A])(f: A => Boolean): Mlist[A] = as filter f
def flatMap[A, B](as: Mlist[A])(f: A => Mlist[B]): Mlist[B] = as flatMap f
}
注意到每对中的方法,实现方法和委托方法如何变得更简单了吗?这是一个好兆头。
对于任何有问题的 synax,我提前表示歉意。我正在学习一门新语言,非常感谢您的帮助!
出于学习的目的,我正在尝试设置一个自定义列表实现(名为 Mlist,用于 'my list'),它可以与 Scala 的理解一起使用。在尝试这样做时,我 运行 遇到了一个让我难过的编译错误。
这是有问题的代码:
sealed trait Mlist[+A] {
def map[A,B](f: A => B): Mlist[B]
def flatMap[A,B](f: A => Mlist[B]): Mlist[B]
def filter[A](f: A => Boolean): Mlist[A]
}
case object Mnil extends Mlist[Nothing] {
def map[A,B](f: A => B): Mlist[B] = {
Mnil
}
def flatMap[A, B](f: A => Mlist[B]): Mlist[B] = {
Mnil
}
def filter[A](f: A => Boolean): Mlist[A] = {
Mnil
}
}
case class Mcons[+A](head: A, tail: Mlist[A]) extends Mlist[A] {
def map[A,B](f: A => B): Mlist[B] = {
Mlist.map(this)(f)
}
def flatMap[A,B](f: A => Mlist[B]): Mlist[B] = {
Mlist.flatMap(this)(f)
}
def filter[A](f: A => Boolean): Mlist[A] = {
Mlist.filter(this)(f)
}
}
object Mlist {
def map[A,B](l: Mlist[A])(f: A => B): Mlist[B] = {
foldRight(l, Mnil: Mlist[B])((h, t) => Mcons(f(h), t))
}
def filter[A](as: Mlist[A])(f: A => Boolean): Mlist[A] = {
foldRight(as, Mnil: Mlist[A])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
}
def flatMap[A, B](as: Mlist[A])(f: A => Mlist[B]): Mlist[B] = {
concat(map(as)(f))
}
}
object Mlist {
def map[A,B](l: Mlist[A])(f: A => B): Mlist[B] = {
foldRight(l, Mnil: Mlist[B])((h, t) => Mcons(f(h), t))
}
def filter[A](as: Mlist[A])(f: A => Boolean): Mlist[A] = {
foldRight(as, Mnil: Mlist[A])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
}
def flatMap[A, B](as: Mlist[A])(f: A => Mlist[B]): Mlist[B] = {
concat(map(as)(f))
}
}
基本思想是有一个trait来定义我的两个Mlist实现的方法类。我没有为 map 之类的东西重新实现实例方法,而是尝试调用我的帮助程序对象以重用它的方法。
这是我看到的编译错误:
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:31: type mismatch;
[error] found : A(in method map) => B
[error] required: A(in class Mcons) => B
[error] Mlist.map(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:35: type mismatch;
[error] found : A(in method flatMap) => Mlist[B]
[error] required: A(in class Mcons) => Mlist[B]
[error] Mlist.flatMap(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:39: type mismatch;
[error] found : A(in method filter) => Boolean
[error] required: A(in class Mcons) => Boolean
[error] Mlist.filter(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:39: type mismatch;
[error] found : Mlist[A(in class Mcons)]
[error] required: Mlist[A(in method filter)]
[error] Mlist.filter(this)(f)
而且,如果它真的有用,下面是我最终打算实现的(未经测试且可能完全功能失调的)理解:
def combos(list: Mlist[A]): Mlist[Mlist[A]] = {
for {
el <- list
combo <- combos(tail(list))
} yield {
setHead(el, combo)
}
}
任何人都可以告诉我我的编译错误是什么意思以及如何解决它们吗?
您正在使用 Mlist.map
、Mlist.flatMap
和 [=20] 中的同名类型参数隐藏 Mlist
特征中定义的类型参数 A
=] 方法:
sealed trait Mlist[+A] {
// ↑
// this is a type parameter named `A`
def map[A,B](f: A => B): Mlist[B]
// ↑
// this is a completely different, totally unrelated type parameter,
// confusingly also named `A`
def flatMap[A,B](f: A => Mlist[B]): Mlist[B]
def filter[A](f: A => Boolean): Mlist[A]
}
Scala 在错误消息中告诉您这一点,它在同名 A
s 和 which 参数名称后的括号中告诉您=22=]它在谈论:
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:31: type mismatch;
[error] found : A(in method map) => B
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] required: A(in class Mcons) => B
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] Mlist.map(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:35: type mismatch;
[error] found : A(in method flatMap) => Mlist[B]
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] required: A(in class Mcons) => Mlist[B]
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] Mlist.flatMap(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:39: type mismatch;
[error] found : A(in method filter) => Boolean
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] required: A(in class Mcons) => Boolean
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] Mlist.filter(this)(f)
[error] ^
[error] /Users/jb/Desktop/dev/personal/functional-programming-scala/src/main/scala/Ch3Lists.scala:39: type mismatch;
[error] found : Mlist[A(in class Mcons)]
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] required: Mlist[A(in method filter)]
// ↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
[error] Mlist.filter(this)(f)
也许,如果您在所有地方都使用新名称并且不隐藏任何内容,错误消息可能会变得更清楚:
sealed trait Mlist[+A] {
def map[B, C](f: B => C): Mlist[C]
def flatMap[D, E](f: D => Mlist[E]): Mlist[E]
def filter[F](f: F => Boolean): Mlist[F]
}
case object Mnil extends Mlist[Nothing] {
def map[G, H](f: G => H): Mlist[H] = this
def flatMap[I, J](f: I => Mlist[J]): Mlist[J] = this
def filter[K](f: K => Boolean): Mlist[K] = this
}
case class Mcons[+L](head: L, tail: Mlist[L]) extends Mlist[L] {
def map[M, N](f: M => N): Mlist[N] = Mlist.map(this)(f)
def flatMap[O, P](f: O => Mlist[P]): Mlist[P] = Mlist.flatMap(this)(f)
def filter[Q](f: Q => Boolean): Mlist[Q] = Mlist.filter(this)(f)
}
object Mlist {
def map[R, S](l: Mlist[R])(f: R => S): Mlist[S] =
foldRight(l, Mnil: Mlist[S])((h, t) => Mcons(f(h), t))
def filter[T](as: Mlist[T])(f: T => Boolean): Mlist[T] =
foldRight(as, Mnil: Mlist[T])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
def flatMap[U, V](as: Mlist[U])(f: U => Mlist[V]): Mlist[V] =
concat(map(as)(f))
}
这给出了以下错误消息:
<console>:24: error: type mismatch;
found : M => N
required: L => N
def map[M, N](f: M => N): Mlist[N] = Mlist.map(this)(f)
^
<console>:25: error: type mismatch;
found : O => Mlist[P]
required: L => Mlist[P]
def flatMap[O, P](f: O => Mlist[P]): Mlist[P] = Mlist.flatMap(this)(f)
^
<console>:26: error: type mismatch;
found : Q => Boolean
required: L => Boolean
def filter[Q](f: Q => Boolean): Mlist[Q] = Mlist.filter(this)(f)
^
<console>:26: error: type mismatch;
found : Mlist[L]
required: Mlist[Q]
def filter[Q](f: Q => Boolean): Mlist[Q] = Mlist.filter(this)(f)
^
我希望现在可以清楚地看到您的错误来自何处。
请注意,您实际上从未在任何地方使用特征或 class 的类型参数,您 总是 仅使用方法的类型参数。这肯定听起来很可疑;您需要实际使用这些类型参数!
sealed trait Mlist[+A] {
def map[B](f: A => B): Mlist[B]
def flatMap[B](f: A => Mlist[B]): Mlist[B]
def filter(f: A => Boolean): Mlist[A]
}
case object Mnil extends Mlist[Nothing] {
def map[A, B](f: A => B): Mlist[B] = this
def flatMap[A, B](f: A => Mlist[B]): Mlist[B] = this
def filter[A](f: A => Boolean): Mlist[A] = this
}
case class Mcons[+A](head: A, tail: Mlist[A]) extends Mlist[A] {
def map[B](f: A => B): Mlist[B] = Mlist.map(this)(f)
def flatMap[B](f: A => Mlist[B]): Mlist[B] = Mlist.flatMap(this)(f)
def filter(f: A => Boolean): Mlist[A] = Mlist.filter(this)(f)
}
object Mlist {
def map[A, B](l: Mlist[A])(f: A => B): Mlist[B] =
foldRight(l, Mnil: Mlist[B])((h, t) => Mcons(f(h), t))
def filter[A](as: Mlist[A])(f: A => Boolean): Mlist[A] =
foldRight(as, Mnil: Mlist[A])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
def flatMap[A, B](as: Mlist[A])(f: A => Mlist[B]): Mlist[B] =
concat(map(as)(f))
}
顺便说一句,我认为你的抽象是错误的方式:当然,外部对象如 Mlist
单例对象应该 不 知道内部Mcons
个对象并操纵它们!一个对象应该知道如何操纵自己,而其他人不应该知道这一点。事实上,您的抽象奇怪地混合在一起:Mnil
知道如何处理自身,但 Mcons
对象不知道。这样看起来更清醒:
case class Mcons[+A](head: A, tail: Mlist[A]) extends Mlist[A] {
def map[B](f: A => B): Mlist[B] = foldRight(Mnil: Mlist[B])((h, t) => Mcons(f(h), t))
def flatMap[B](f: A => Mlist[B]): Mlist[B] = concat(map(f))
def filter(f: A => Boolean): Mlist[A] =
foldRight(Mnil: Mlist[A])((a, acc) => if (f(a)) Mcons(a, acc) else acc)
}
object Mlist {
def map[A, B](l: Mlist[A])(f: A => B): Mlist[B] = l map f
def filter[A](as: Mlist[A])(f: A => Boolean): Mlist[A] = as filter f
def flatMap[A, B](as: Mlist[A])(f: A => Mlist[B]): Mlist[B] = as flatMap f
}
注意到每对中的方法,实现方法和委托方法如何变得更简单了吗?这是一个好兆头。