Option [Int]的条件映射通过使用scalaz的函数对

时间:2013-11-10 01:14:06

标签: scala scalaz

我有一对Option[Int],想要找到两个值中的最小值,如果它们都存在,否则只是其中之一。假设我有一个函数minOption

def minOption(a: Option[Int], b: Option[Int]): Option[Int]

我想要的是以下输入到输出的映射:

(Some(a), Some(b)) => Some(Math.min(a,b))
(Some(a), None) => Some(a)
(None, Some(b)) => Some(b)
(None, None) => None

有一种简单的方法吗?我无法想出使用嵌套模式匹配的明显方式。

我认为这在scalaz中应该是微不足道的,但我对它还不是很熟悉,也找不到方法。

2 个答案:

答案 0 :(得分:6)

有一个用Label.MinVal标记的东西的半群,它选择最小值:

scala> import scalaz._ ; import Scalaz._ ; import Tags._
import scalaz._
import Scalaz._
import Tags._

scala> MinVal(3).some |+| MinVal(1).some
res0: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = Some(1)

scala> MinVal(3).some |+| none[Int @@ MinVal]
res1: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = Some(3)

scala> none[Int @@ MinVal] |+| none[Int @@ MinVal]
res2: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = None

在上文中,Int @@ MinValInt的子类型,已使用MinVal“标记”,这有助于选择正确的半群。 MinVal(x: Int)返回类型为Int @@ MinVal的x。 x.someSome(x)类似,但类型为Option而不是Some,这有助于类型推断(有一个Semigroup for Option,但不适用于Some),类似none[T]返回None,但其类型为Option[T]而不是None(由于同样的原因,没有半群为无,但有一个用于选项)< / p>

如果有两个以上,也许你有一个列表,你可以使用suml

scala> List(MinVal(2).some, None, MinVal(3).some, None, MinVal(1).some).suml
res5: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = Some(1)

答案 1 :(得分:3)

我认为您不需要Scalaz:假设您的选项包含在列表中(也使用varargs)

 def findMinOpt(li: List[Option[Int]]): Option[Int] =
    {
      val listwithoutOptions = li.flatten
      listwithoutOptions.reduceLeftOption(_ min _)
    }


 def findMinOptVarArgs(li: Option[Int]*): Option[Int] =
    {
      val listwithoutOptions = li.flatten
      listwithoutOptions.reduceLeftOption(_ min _)
    }