我可以让 Scala 在这里推断 Option 类型吗?
Can I get Scala to infer the Option type here?
我想调用一个通用函数 f[X](...)
,在我的例子中 X
恰好是 Option[Y]
。我尝试在函数需要 X
的地方传递 Some[...]
和 None
,但 Scala 坚持认为 X
是 Some[Y]
.
类型
def flattenOptionMap[A, B](input : Map[A, Option[B]]) : Option[Map[A, B]] = {
input.foldLeft[Option[Map[A,B]]] (Some(Map.empty)) {
case (_, (_, None)) => None
case (None, (_, _)) => None
case (Some(acc), (key, Some(value))) => Some(acc + (key -> value))
}
}
在这个例子中,我必须明确指定 Option[Map[A,B]]
应该用作 foldLeft
的通用类型。所有必要的类型信息都已包含在上下文中,在我看来,输入像 Option[Map[A,B]]
这样繁琐的类型的次数超过必要的次数会大大降低我的代码的可读性。
有没有办法让 Scala 最终推断类型,或者避免复制粘贴整个类型?
如果您的目标是提高可读性,并从编译器那里获得帮助来推断类型,请尝试:
def flattenOptionMap[A, B](input: Map[A, Option[B]]) =
input.foldLeft(Option(Map.empty[A, B])) {
case (_, (_, None)) => None
case (None, (_, _)) => None
case (Some(acc), (key, Some(value))) => Some(acc + (key -> value))
}
甚至更好:
def flattenOptionMap[A, B](input: Map[A, Option[B]]) =
input.foldLeft(Option(Map.empty[A, B])) {
case (Some(acc), (key, Some(value))) => Some(acc + (key -> value))
case _ => None
}
或甚至更好(在我看来):Peter Neyens 的回答。使用 Traverse
实例中的 sequence
。
当您使用 Option(Map.empty[A, B])
作为 foldLeft
的起始值时,Scala 将推断出正确的类型,正如我在评论中所写的(以及他的回答中的 beefyhalo)。
我想补充一点,如果您愿意使用 Scalaz,您可以只使用 sequence
功能。
import scalaz._
import Scalaz._
val mapSome = Map(1 -> Some("a"), 2 -> Some("b"))
val mapNone = Map(1 -> Some("a"), 2 -> Some("b"), 3 -> None)
mapSome.sequence
flattenOptionMap(mapSome)
// Option[Map[Int,String]] = Some(Map(1 -> a, 2 -> b))
mapNone.sequence
flattenOptionMap(mapNone)
// Option[Map[Int,String]] = None
我想调用一个通用函数 f[X](...)
,在我的例子中 X
恰好是 Option[Y]
。我尝试在函数需要 X
的地方传递 Some[...]
和 None
,但 Scala 坚持认为 X
是 Some[Y]
.
def flattenOptionMap[A, B](input : Map[A, Option[B]]) : Option[Map[A, B]] = {
input.foldLeft[Option[Map[A,B]]] (Some(Map.empty)) {
case (_, (_, None)) => None
case (None, (_, _)) => None
case (Some(acc), (key, Some(value))) => Some(acc + (key -> value))
}
}
在这个例子中,我必须明确指定 Option[Map[A,B]]
应该用作 foldLeft
的通用类型。所有必要的类型信息都已包含在上下文中,在我看来,输入像 Option[Map[A,B]]
这样繁琐的类型的次数超过必要的次数会大大降低我的代码的可读性。
有没有办法让 Scala 最终推断类型,或者避免复制粘贴整个类型?
如果您的目标是提高可读性,并从编译器那里获得帮助来推断类型,请尝试:
def flattenOptionMap[A, B](input: Map[A, Option[B]]) =
input.foldLeft(Option(Map.empty[A, B])) {
case (_, (_, None)) => None
case (None, (_, _)) => None
case (Some(acc), (key, Some(value))) => Some(acc + (key -> value))
}
甚至更好:
def flattenOptionMap[A, B](input: Map[A, Option[B]]) =
input.foldLeft(Option(Map.empty[A, B])) {
case (Some(acc), (key, Some(value))) => Some(acc + (key -> value))
case _ => None
}
或甚至更好(在我看来):Peter Neyens 的回答。使用 Traverse
实例中的 sequence
。
当您使用 Option(Map.empty[A, B])
作为 foldLeft
的起始值时,Scala 将推断出正确的类型,正如我在评论中所写的(以及他的回答中的 beefyhalo)。
我想补充一点,如果您愿意使用 Scalaz,您可以只使用 sequence
功能。
import scalaz._
import Scalaz._
val mapSome = Map(1 -> Some("a"), 2 -> Some("b"))
val mapNone = Map(1 -> Some("a"), 2 -> Some("b"), 3 -> None)
mapSome.sequence
flattenOptionMap(mapSome)
// Option[Map[Int,String]] = Some(Map(1 -> a, 2 -> b))
mapNone.sequence
flattenOptionMap(mapNone)
// Option[Map[Int,String]] = None