假设我有两个函数foo: Int => Option[Int]
和bar: Int => Option[Int]
并使用它们来处理列表:
val xs: List[Int] = ...
xs flatMap {x => foo(x) orElse bar(x)}
我可以写xs flatMap (foo orElse bar)
代替{x => foo(x) orElse bar(x)}
吗?
我可以使用3d派对库。
答案 0 :(得分:6)
据我所知,标准库中没有此类内容,但您可以使用implicit class自行添加:
implicit class WithOrElse[T, R](f: T => Option[R]) {
def orElse(g: T => Option[R])(x: T) = f(x) orElse g(x)
}
示例:
val foo: Int => Option[Int] = x => if (x % 2 == 0) Some(x) else None
val bar: Int => Option[Int] = x => if (x % 3 == 0) Some(x) else None
val xs = List(1, 2, 3, 4, 5, 6, 7, 8)
xs flatMap (foo orElse bar)
答案 1 :(得分:1)
您可以使用scalaz中|+|
类型类的合并操作(Semigroup
)。
Option
的默认半群使用内容的半群,如果两个值都存在,则组合这些值。
因此,要模仿orElse
行为,您需要将Option
包裹在Tags.FirstVal
标记中。
Tags.FirstVal
州的文档:
键入tag以选择一个
scalaz.Semigroup
实例,该实例选择要追加的第一个操作数。
您可以使用.subst
的{{1}}和.unsubst
方法,从Tag
内部包装和解包类型T
。在我看来,你必须通过类型推断来帮助Scala。
总而言之,组合功能如下所示:
F[T]
要将其与type F[T] = Int => Option[T]
val f = Tags.FirstVal.unsubst(
Tags.FirstVal.subst[F, Int](foo) |+|
Tags.FirstVal.subst[F, Int](bar))
一起使用,您必须以某种方式使用从flatMap
到Option
的隐式转换。因此List
调用可能如下所示:
flatMap
如果您覆盖xs flatMap (f(_))
的隐式|+|
实例,也可以使orElse
工作为Monoid
:
Option