2014-01-16 116 views
5

的匹配数组我有:斯卡拉 - 选项

val foo = Some(List(1, 2, 3)) -> Some("y") 

我想投的比赛吧:

foo match { 
    case (Some(x), Some(y)) => println(x + " " + y) 
    case _ => println("error") 

这工作正常Some(List(1, 2, 3) -> Some("score"))但失败了Some(List(1, 2, 3) -> NoneNone -> Some("y")None -> None

error: constructor cannot be instantiated to expected type; 
    found : Some[A] 
    required: None.type 
error: not found: value ... 

这是为什么?

当然,我可以使用getOrElse(),但看起来并不那么优雅。

THX很多, 卡斯滕

更新:

foo match { 
case (x: Some[List[Int]], y: Some[Int]) => println(x.get) 
case _ => println("error") 
} 

失败以及与:

error: pattern type is incompatible with expected type; 
found : Some[Int] 
required: None.type 

我认为case _将采取照顾。

回答

6

这是编译器告诉你一些事情。如果你有一个像

val foo = Some(List(1, 2, 3)) -> None 

表达这将有类型(某些[列表[INT]],None.type),您可以轻松地从斯卡拉控制台中输入表情看

scala> val foo = Some(List(1, 2, 3)) -> None 
foo: (Some[List[Int]], None.type) = (Some(List(1, 2, 3)),None) 

所以你知道在编译时元组的第二个元素只能是None,与Some匹配永远不会成功。因此错误信息。

如果你给foo一个限制较少的类型,它将起作用。

val foo : (Option[List[Int]], Option[String]) = Some(List(1, 2, 3) -> None 

请注意,这是完全相同的。匹配一些永远不会发生的事情几乎肯定是一个错误。你必须上传到任何以避免编译时错误(但然后你会得到一个运行时错误。

+0

嗯,这是有道理的。但是,foo._1和foo._2可能被定义。这就是我想要的知道。 – Karsten

+0

好吧,现在我明白了,我认为foo会是type(选项[List [Int]],Option [Any]) – Karsten

+0

你可以这样做,但scala语言设计者决定给一些和无它自己的类型,所以这样的事情可以在编译时找到 这通常不是真正的代码中的问题,因为您将foo定义为您想处理的最通用类型,例如(Option [List [Int ]],Option [String])。 –

2

在下面的代码,斯卡拉将得到一个编译错误上foo match但编译与foo2/foo3正常运行:

val foo = None -> None 
val foo2: (Option[Any], Option[Any]) = None -> None 
val foo3: (Option[Any], Option[Any]) = foo 

foo match { 
    case (Some(x), Some(y)) => println(x + " " + y) 
    case _ => println("error") 
}