2

我有一对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,但我对它还不是很熟悉,也找不到方法。

4

2 回答 2

6

有一个用 Tags.MinVal 标记的事物的半群,它选择最小 val:

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 @@ MinVal是一个类型,它是 的子类型Int,它已经被“标记”了MinVal,这有助于选择正确的半群。 MinVal(x: Int)返回 x 的类型Int @@ MinValx.some就像,Some(x)除了类型是Option代替Some,这有助于类型推断(对于 Option 有一个 Semigroup,但对于 Some 没有),类似地none[T]返回None,但它的类型是Option[T]而不是None(出于同样的原因有帮助,没有 Semigroup无,但有一个选项)

如果有两个以上,也许您有这些列表,您可以使用suml

scala> List(MinVal(2).some, None, MinVal(3).some, None, MinVal(1).some).suml
res5: Option[scalaz.@@[Int,scalaz.Tags.MinVal]] = Some(1)
于 2013-11-10T02:26:05.000 回答
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 _)
    }
于 2013-11-10T03:08:37.087 回答