type inference and for expression in scala

This works

val keys Option[List[Option[String]]] = someFunctionThatReturnsKeys()
val tries = for (
    unwrapped <- keys) {
        for(keyOption <- unwrapped;
            stripped <- keyOption if stripped.contains(":")) 
        yield Try(java.lang.Long.parseLong(stripped.substring(stripped.lastIndexOf(":") + 1)))         }

This does not work.

val tries = for (
              unwrapped <- keys;
              keyOption <- unwrapped;
               stripped <- keyOption if stripped.contains(":")) 
            yield Try(java.lang.Long.parseLong(stripped.substring(stripped.lastIndexOf(":") + 1)))

The error is for the line

keyOption <- unwrapped;

The error is displayed as

type mismatch; found : List[scala.util.Try[Long]] required: Option[?]

I am using eclipse ide with scala 2.10

Why is the type inference failing?


Type inference isn't failing, it's that the for desugars into a flatMap , and Option doesn't know how to flatten anything but another Option .

What do you want the return type to be? That will determine what you actually want to do. For instance, if you want a list:

val tries = for {
  unwrapped <- keys.toList;
  keyOption <- unwrapped;
  stripped <- keyOption if stripped.contains(":")
} yield Try(stripped.substring(1 + stripped.lastIndexOf(":")).toLong)

will do the trick. You'll get a List[Try[Long]] , which will be empty if the outer Option was None .

If you want to keep the outer option, you really want a map not a flatMap at the outside, which is more easily written like so:

val tries2 = keys.map(unwrapped => for {
  keyOption <- unwrapped;
  stripped <- keyOption if stripped.contains(":")
} yield Try(stripped.substring(1 + stripped.lastIndexOf(":")).toLong))

This will give you an Option[List[Try[Long]]] .

链接地址: http://www.djcxy.com/p/38020.html

上一篇: 推断列表类型与任一和选项

下一篇: 类型推断和scala中的表达式