scala - 当类在Scala中定义.map函数时,是否可以通过继承(或其他方式)来了解?

标签 scala

我的问题在下面的代码中表达。
我正在尝试获取一些具有.map函数的输入。我知道,如果我调用.map,它将返回一个Int给我。

  // In my case, they are different representations of Ints
  // By that I mean that in the end it all boils down to Int
  val list: Seq[Int] = Seq(1,2,3,4)
  val optInt: Option[Int] = Some(1)
  // I can use a .map with a Seq, check!
  list.map {
    value => println(value)
  }
  // I can use it with an Option, check!
  optInt.map {
    value => println(value)
  }
  // Well, you're asking yourself why do I have to do it,
  // Why don't I use foreach to solve my problem. Check!
  list.foreach(println)
  optInt.foreach(println)

  // The problem is that I don't know what I'm going to get as input
  // The only thing I know is that it's "mappable" (it has the .map function)
  // And that if I were to apply .map it would return Ints to me
  // Like this:
  def printValues(genericInputThatHasMap: ???) {
    genericInputThatHasMap.map {
      value => println(value)
    }
  }

  // The point is, what do I have to do to have this functionality?
  // I'm researching right now, but I still haven't found anything.
  // That's why I'm asking it here =(

  // this works:
  def printValues(genericInputThatHasMap: Seq[Int]) {
    genericInputThatHasMap.map {
      value => println(value)
    }
  }

提前致谢!干杯!

最佳答案

首先快速了解有关mapforeach的信息。如果您只想对集合中的每个项目执行带有副作用的操作(例如打印到标准输出或文件等),请使用foreach。如果您有兴趣通过转换旧元素中的每个元素来创建新集合,请使用map。实际上,当您编写xs.map(println)时,您将打印出集合的所有元素,但是您还将获得(完全无用的)单位集合,并且还可能使将来希望使用foreach的代码的读者(包括您自己)感到困惑。在这样的情况下使用。

现在解决您的问题。在我看来,您已经遇到了Scala标准库中最丑陋的疣之一-名为mapforeach(和flatMap)的方法在语言级别上得到了神奇的对待,而该语言级别与特定类型无关定义它们。例如,我可以这样写:

case class Foo(n: Int) {
  def foreach(f: Int => Unit) {
    (0 until n) foreach f
  }
}

并像这样在for循环中使用它,仅仅是因为我已将我的方法命名为foreach:
for (i <- Foo(10)) println(i)

您可以使用structural types在自己的代码中执行类似的操作:
def printValues(xs: { def foreach(f: (Int) => Unit): Unit }) {
  xs foreach println
}

在这里,任何具有适当类型的xs方法的foreach(例如Option[Int]List[Int])都将按预期方式编译和运行。

但是,当您尝试使用mapflatMap时,结构化类型会变得更加困惑,并且在其他方​​面也不令人满意-例如,由于它们使用了运行时反射,它们会带来一些难看的开销。实际上,由于这些原因,它们必须为explicitly enabled in Scala 2.10以避免发出警告。

正如senia的答案所指出的,Scalaz library通过使用type classes之类的Monad,为问题提供了更加一致的方法。但是,在这种情况下,您不想使用Monad:它比您需要的功能强大得多。您将使用Each提供foreach,并为Functor提供map。例如,在Scalaz 7中:
import scalaz._, Scalaz._

def printValues[F[_]: Each](xs: F[Int]) = xs foreach println

或者:
def incremented[F[_]: Functor](xs: F[Int]) = xs map (_ + 1)

总而言之,您可以使用结构化类型以标准的,惯用的但丑陋的方式来完成所需的操作,或者可以使用Scalaz获得更干净的解决方案,但要以增加新的依赖关系为代价。

关于scala - 当类在Scala中定义.map函数时,是否可以通过继承(或其他方式)来了解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13893730/

相关文章:

scala - Spark 和 Azure-Cosmosdb 的跨版本冲突

scala - Spark分析异常: Path does not exist: Azure Blob Storage

java - 在 IntelliJ IDE 中将 Spark 与 Scala 项目集成时出错

scala - 如果数据结构是可折叠的,它是幺半群吗?

scala - 使用自定义名称 Play WebSocketActor createHandler

Scala -> 函数

java - 如何将 Scala 案例类和集合桥接到 Java

scala - 具有Java库的Scala Gradle控制台应用程序

string - toString.map 和 toString.toArray.map 的性能差异

scala - 如何在 Scala 中获取泛型函数的实际类型?