【发布时间】:2014-04-29 11:54:55
【问题描述】:
我想使用 Scala 的“monadic-for”在最后获得 Some(x) 或 None。
这意味着,这个 monad 中的第一个元素必须是一个 Option。
问题是,有时我没有选项可以开始。
所以我“伪造”了一个,使用一个虚拟值。
抽象形式如下:
for {
// only used to yield Some/None at the end
dummyVal <- Some("dummy value")
// ...
// ... other monadic expressions
// ...
} yield {
// result which will be wrapped into Some(...)
}
一个具体的例子可以是:
case class Person(name:String, age:Int)
val p = Person("John", 32)
最后计算为Some("John"):
for {
dummy <- Some("dummy")
matchedPerson = p
if matchedPerson.age > 30
} yield {
matchedPerson.name
}
而这计算为None:
for {
dummy <- Some("dummy")
matchedPerson = p
if matchedPerson.age > 55
} yield {
matchedPerson.name
}
虽然我得到了我想要的(一个评估为 Option 的 monadic-for),但我有一种不好的感觉。我不得不从一个“虚拟”Option 开始“滥用”monadic-for,只是为了最后得到Some/None。
我的问题是:有没有更好的方法来实现这一点,而不创建一个虚拟值?
更新:
考虑这个建立在上述例子之上的例子:
case class Person(name: String, username: String, age: Int)
case class Session(loggedInPerson: Person)
def isValidUser(username: String):Boolean = ???
def isValidPassword(username: String, password: String):Boolean = ???
def readPassword():Option[String] = ???
val usr = Person("John Wayne", "jwayne", 55)
for {
dummy <- Some("does not matter")
username = usr.username
if isValidUser(username)
pass <- readPassword()
if isValidPassword(username, pass)
} yield {
Session(usr)
}
现在很明显,“for”很长,使用过滤器、flatMaps 等重写可能不切实际。
最后我的目标是获得Option[Session]。我从一个虚拟的Some 值开始“强制”这个结果。
但正如Noel M所指出的,我可以重写:
dummy <- Some("does not matter")
与:
usr <- Some(usr)
【问题讨论】: