Scala&用于推导:在将map,flatmap和filter实现为依赖于伴随对象的实例方法时编译错误



我对任何可疑的同步事先表示歉意。我正在学习一种新语言,绝对感谢您的帮助!

为了学习目的,我正在尝试设置可以与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))
  }
}

基本思想是具有定义我两个MLIST类实现的方法的特征。我没有为地图等重新进来实例方法,而是试图调用我的助手对象以重复使用其方法。

这是我看到的编译错误:

[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特征中定义的类型参数A,在您的Mlist.mapMlist.flatMapMlist.filter方法中具有相同名称的类型参数:

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和 B s的是:

[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)
                                                                    ^

我希望现在清楚地看到您的错误来自哪里。

请注意,您实际上永远不会在任何地方使用特质或类的类型参数,您始终仅使用方法的类型参数。这肯定听起来很腥;您需要实际使用这些类型参数!

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 Singleton对象之类的外部对象应该不知道Mcons对象的内部并操纵它们!一个对象应该知道如何操纵自己,没有其他人应该知道这一点。实际上,您的抽象是奇怪的混合在一起的: Mnil do 知道如何处理自己,但是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
}

请注意,每对的两个方法,实现方法和委托Mehod如何变得更简单?这是一个好兆头。

相关内容

  • 没有找到相关文章