我有一个集合 A,我需要从集合 A 创建一个集合 B。在最简单的情况下,人们可能希望使用该map
方法,但我正在寻找一种解决方案,在创建 B 的元素的每个步骤中,它需要访问集合中已有的元素。
我想到了创建 B 的多种可能性:
- 对 B 使用可变集合,然后将其转换为不可变集合
- 使用集合 B 底层的构建器
- 使用带有空 B 的 foldLeft 并将其增长到闭包内
有没有一种惯用的方法,或者至少有一种方法可以根据不同的用例来选择一种方法?
我有一个集合 A,我需要从集合 A 创建一个集合 B。在最简单的情况下,人们可能希望使用该map
方法,但我正在寻找一种解决方案,在创建 B 的元素的每个步骤中,它需要访问集合中已有的元素。
我想到了创建 B 的多种可能性:
有没有一种惯用的方法,或者至少有一种方法可以根据不同的用例来选择一种方法?
最惯用的是foldLeft
——折叠在函数式编程中非常自然。另一种可能性是 a scanLeft
,这可能会稍微减少簿记。
另一方面,这实际上看起来像是对State
monad 的迭代。《 Scala 中的函数式编程》一书将类似的内容作为其练习之一。
State
monad 基本上是 monadA
函数的类型S => (S, A)
,尽管它通常被声明为具有一些特殊方法的适当类型,这些方法使常见操作更容易。
在您的示例中,状态 ,S
将是Option[A]
最后一个结果的一个(或者,如果合适的话,是 的“零” A
)。然后,您将集合从它的类型映射T
到S => (S, A)
(或 state monad 类型)的函数,得到一个Coll[S => (S, A)]
.
从那里你可以sequence
得到它(对于 monads来说变成了sequence
一些东西- 请参阅迭代器模式的本质),获取,为其提供初始状态,然后检索.M[N[A]]
N[M[A]]
M
N
S => (S, Coll[A])
Coll[A]
网上有很多关于 state monad 的资源,尽管我个人发现它比大多数其他 monad 更难掌握。有人向我提到这可能是因为“状态” monad 命名错误,它实际上是一个“状态处理器” monad,这对我来说很有意义。
无论如何,从您的替代方案来看,这foldLeft
是最惯用的,但 state monad 方法非常适合这项任务。
我当然会争辩说 foldLeft 是最惯用的方法。这正是我在阅读您的可能性之前的想法。