Scala 如何使用orElse组合返回选项的函数?

Scala 如何使用orElse组合返回选项的函数?,scala,pointfree,Scala,Pointfree,假设我有两个函数foo:Int=>Option[Int]和bar:Int=>Option[Int],并使用它们处理列表: val xs: List[Int] = ... xs flatMap {x => foo(x) orElse bar(x)} 我可以写xs平面图(foo-orElse-bar)而不是{x=>foo(x)orElse-bar(x)}? 我可以使用3d party library。据我所知,标准库中没有类似的功能,但您可以使用: 例如: val foo: Int =>

假设我有两个函数
foo:Int=>Option[Int]
bar:Int=>Option[Int]
,并使用它们处理列表:

val xs: List[Int] = ...
xs flatMap {x => foo(x) orElse bar(x)}
我可以写
xs平面图(foo-orElse-bar)
而不是
{x=>foo(x)orElse-bar(x)}


我可以使用3d party library。

据我所知,标准库中没有类似的功能,但您可以使用:

例如:

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)

您可以使用scalaz中的
半组
类型类的组合操作(
++

选项的默认半组
使用内容的半组,如果两个值都存在,则组合值。 因此,要模拟
orElse
行为,您需要将
选项
s包装在
标记.FirstVal
标记中

Tags.FirstVal
的文档说明:

键入标记以选择选择要追加的第一个操作数的
scalaz.Semigroup
实例

您可以使用
标记的
.subst
.unsubst
方法,从一些
F[T]
内部包装和打开类型
T
。在我看来,您还必须帮助Scala进行一些类型推断

总之,组合函数如下所示:

type F[T] = Int => Option[T]
val f = Tags.FirstVal.unsubst(
  Tags.FirstVal.subst[F, Int](foo) |+| 
  Tags.FirstVal.subst[F, Int](bar))
xs flatMap (f(_))
要将它与
flatMap
一起使用,您必须以某种方式使用隐式转换from to
选项
to
List
。因此,
flatMap
调用可能如下所示:

type F[T] = Int => Option[T]
val f = Tags.FirstVal.unsubst(
  Tags.FirstVal.subst[F, Int](foo) |+| 
  Tags.FirstVal.subst[F, Int](bar))
xs flatMap (f(_))

如果覆盖
选项的隐式
幺半群
实例,也可以使
+
作为
工作:

import scalaz._, Scalaz._
implicit val inst: Monoid[Option[Int]] = 
  Tags.First.unsubst(scalaz.std.option.optionFirst[Int])

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 |+| bar)(_))

谢谢它是否在猫或任何其他3d派对库中提供?Foo。比我快一分钟。对
foo
bar
的定义完全相同。幽灵般的有一个+1:)这个答案似乎有点不对劲,因为你想要更地道的东西,但我把它放在这里,因为我相信这是使用基本scalaz/cats完成的方式。答案很好。)这就是我要找的。@Michael,我已经更新了一种方法,使
+
orElse
一样出色!多谢各位<代码>|+|
看起来不错。