如何将函数应用于Scala中的选项列表?

时间:2015-03-26 14:17:13

标签: scala scalaz applicative

假设我有一个函数f: (Int, Int, Int) => String。我可以轻松地将它应用于Option[Int]类型的三个参数:

def foo(f: (Int, Int, Int) => String,
        ox: Option[Int],
        oy: Option[Int],
        oz: Option[Int]): Option[String] = ox <*> (oy <*> (oz <*> f.curried.some))  

现在假设我需要将f应用于列表ois: List[Option[Int]]的前三个元素。例如:

List() => None
List(1.some, 2.some) => None
List(1.some, None, 2.some, 3.some) => None
List(1.some, 2.some, 3.some, 4.some) => Some(f(1, 2, 3))
List(1.some, 2.some, 3.some, None) => Some(f(1, 2, 3))

你会如何实现它?

1 个答案:

答案 0 :(得分:4)

您可以将Optiontakeflattencollect一起用于一个非常干净的版本:

def foo(f: (Int, Int, Int) => String, ois: List[Option[Int]]) = 
    Option(ois.take(3).flatten) collect {
        case List(a, b, c) => f(a, b, c)
}
如果前三个元素为ois.take(3).flatten,则

List(a,b,c)仅匹配Some。您将变量包装在Option中以启用所需的collect语义(这样部分函数miss将返回None,并且部分函数的返回将包含在Some中})。