我现在正在阅读红书“Scala 中的函数式编程”,所以同时我正在学习 Scala。如果我理解正确,特质并不意味着对象。如果我在这里错了,请纠正我。
我的问题是我不知道如何在将 A 类型的列表包裹在 Some
中时构建它。特征。我会很感激正确方向的提示。
在我正在进行的练习中,我被要求定义一个函数,该函数旨在转换列表中的每个元素,然后将整个列表包含在 Some
中。特征。
这是我的代码:
def traverse[A, B](a: List[A])(f: A => Option[B]): Option[List[B]] = a match {
case Nil => Nil: B
case h :: t => f(h) flatMap ( hh => hh :: traverse(t)(f))
}
我觉得我在这里走在正确的轨道上,但是 scala 解释器提示
::
不适用于 Option[List[B]]
.我认为这是因为函数的类型签名不返回一个列表,它返回一个包含在 Some 中的 List。但是我对 的直觉可以吗?平面 map 也有错?
f(h)
返回 Option[B]
.调用 flatmap 实际上会查看 Option 内部,因此 hh 的类型为 B
正确的?我的逻辑是这样我可以用函数 hh :: traverse(t)(f)
构造一个 B 类型的列表。 .但我不完全确定是否就在这里。如果有任何区别,我将使用带有 :paste 命令的 scala 解释器。我不确定这是否会让事情变得更加糟糕。
最佳答案
If I understand correctly, trait does not mean object.
特质就是特质,对象就是对象。 Traits 有点像 Java 中的“接口(interface)”,
object
s 是单例对象。那些单例对象可以从特征扩展。
Some
trait
Some
不是特征,而是 class extending Option
.it returns a List wrapped within a Some.
它返回一个包含在
Option
中的列表(即,它可以是 None
,根本没有任何列表)。为了调用::
在可选列表值上,您需要另一个 map
:def traverse[A, B](a: List[A])(f: A => Option[B])
: Option[List[B]] = a match {
case Nil => Some(Nil)
case h :: t => f(h) flatMap {
hValue => traverse(t)(f) map {
tValue => hValue :: tValue
}
}
}
您可以缩写为:
def traverse[A, B](a: List[A])(f: A => Option[B])
: Option[List[B]] = a match {
case Nil => Some(Nil)
case h :: t => f(h) flatMap {
hValue => traverse(t)(f) map (hValue :: _)
}
}
或者只使用
for
-立即理解:def traverse[A, B](a: List[A])(f: A => Option[B])
: Option[List[B]] = a match {
case Nil => Some(Nil)
case h :: t => for {
hValue <- f(h)
tValue <- traverse(t)(f)
} yield (hValue :: tValue)
}
关于scala - 在 Scala 中,如何递归地在单个 Some trait 中构造一个列表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52020871/