3

我有一个集合 A,我需要从集合 A 创建一个集合 B。在最简单的情况下,人们可能希望使用该map方法,但我正在寻找一种解决方案,在创建 B 的元素的每个步骤中,它需要访问集合中已有的元素。

我想到了创建 B 的多种可能性:

  • 对 B 使用可变集合,然后将其转换为不可变集合
  • 使用集合 B 底层的构建器
  • 使用带有空 B 的 foldLeft 并将其增长到闭包内

有没有一种惯用的方法,或者至少有一种方法可以根据不同的用例来选择一种方法?

4

2 回答 2

6

最惯用的是foldLeft——折叠在函数式编程中非常自然。另一种可能性是 a scanLeft,这可能会稍微减少簿记。

另一方面,这实际上看起来像是对Statemonad 的迭代。《 Scala 中的函数式编程》一书将类似的内容作为其练习之一。

Statemonad 基本上是 monadA函数的类型S => (S, A),尽管它通常被声明为具有一些特殊方法的适当类型,这些方法使常见操作更容易。

在您的示例中,状态 ,S将是Option[A]最后一个结果的一个(或者,如果合适的话,是 的“零” A)。然后,您将集合从它的类型映射TS => (S, A)(或 state monad 类型)的函数,得到一个Coll[S => (S, A)].

从那里你可以sequence得到它(对于 monads来说变成了sequence一些东西- 请参阅迭代器模式的本质),获取,为其提供初始状态,然后检索.M[N[A]]N[M[A]]MNS => (S, Coll[A])Coll[A]

网上有很多关于 state monad 的资源,尽管我个人发现它比大多数其他 monad 更难掌握。有人向我提到这可能是因为“状态” monad 命名错误,它实际上是一个“状态处理器” monad,这对我来说很有意义。

无论如何,从您的替代方案来看,这foldLeft是最惯用的,但 state monad 方法非常适合这项任务。

于 2013-09-09T10:16:41.853 回答
5

我当然会争辩说 foldLeft 是最惯用的方法。这正是我在阅读您的可能性之前的想法。

于 2013-09-09T10:14:28.963 回答