rob*_*obo 5 collections monads scala
我正在尝试将两个组合Option[Iterable[_]]成一个新的Option[Iterable[_]].如果其中一个(或两个)元素是Some和None,我想返回一个.似乎应该有一种惯用的做法,但我似乎无法找到一个.以下似乎做我想要的,但不是我希望的光滑解决方案.
def merge(
i1: Option[Iterable[_]], i2: Option[Iterable[_]]
): Option[Iterable[_]] = (i1, i2) match {
case (Some(as), Some(bs)) => Some(as ++ bs)
case (a @ Some(as), None) => a
case (None, b @ Some(bs)) => b
case _ => None
}
Run Code Online (Sandbox Code Playgroud)
任何提示都表示赞赏.谢谢!
Tra*_*own 12
如果你愿意忍受一些抽象代数,那么这里有一个很好的概括:在连接下Iterable[_]是一个monoid,其中monoid只是一组东西(在这种情况下是可迭代的集合)和类似于加法的操作(连接)有一些简单的属性和一个标识元素(空集合).
同样,如果A是一个幺半群,那么Option[A]在你的稍微更一般的版本下也是一个幺半群merge:
Some(xs) + Some(ys) == Some(xs + ys)
Some(xs) + None == Some(xs)
None + Some(ys) == Some(ys)
None + None == None
Run Code Online (Sandbox Code Playgroud)
(注意,我们需要A一个幺半群的事实,知道在第一行做什么.)
该Scalaz库捕获所有这些概括其Monoid类型的类,它可以让你写你merge这样的:
import scalaz._, Scalaz._
def merge(i1: Option[Iterable[_]], i2: Option[Iterable[_]]) = i1 |+| i2
Run Code Online (Sandbox Code Playgroud)
哪个按预期工作:
scala> merge(Some(1 to 5), None)
res0: Option[Iterable[_]] = Some(Range(1, 2, 3, 4, 5))
scala> merge(Some(1 to 5), Some(4 :: 3 :: 2 :: 1 :: Nil))
res1: Option[Iterable[_]] = Some(Vector(1, 2, 3, 4, 5, 4, 3, 2, 1))
scala> merge(None, None)
res2: Option[Iterable[_]] = None
Run Code Online (Sandbox Code Playgroud)
(请注意,还有其他操作可以Monoid为Iterable和提供有效的实例Option,但是您的最常用,以及Scalaz默认提供的操作.)
| 归档时间: |
|
| 查看次数: |
383 次 |
| 最近记录: |