使用 |@| 进行验证在斯卡拉
Validation usage with |@| in Scalaz
背景
我有 Map[String,String]
个配置值。我想提取一系列密钥并在其中任何一个丢失时提供有意义的错误消息。例如:
val a = Map("url"->"http://example.com", "user"->"bob", "password"->"12345")
说我想把这个转化成一个案例class:
case class HttpConnectionParams(url:String, user:String, password: String)
现在,我可以简单地使用 for 循环来提取值:
for(url <- a.get("url");
user <- a.get("user");
password <- a.get("password")) yield {
HttpConnectionParams(url,user,password)
}
获得Option[HttpConnectionParams]
。这很好很干净,除非我得到 None
然后我不知道缺少什么。我想提供该信息。
使用 Scalaz 验证
进入scalaz。我使用的是 7.1.3 版本。
根据我能够整理的内容(一个很好的参考是 here)我可以使用析取:
for(url <- a.get("url") \/> "Url must be supplied";
user <- a.get("user") \/> "Username must be supplied";
password <- a.get("password") \/> "Password must be supplied") yield {
HttpConnectionParams(url,user,password)
}
这很好,因为现在我收到一条错误消息,但这是 railway oriented,因为它会在第一次失败时停止。如果我想得到所有的错误怎么办?让我们使用验证和应用程序构建器(又名“|@|”):
val result = a.get("url").toSuccess("Url must be supplied") |@|
a.get("username").toSuccess("Username must be supplied") |@|
a.get("password").toSuccess("Password must be supplied")
result.tupled match {
case Success((url,user,password)) => HttpConnectionParams(url,user,password)
case Failure(m) => println("There was a failure"+m)
}
问题
这符合我的预期,但我对用法有一些疑问:
- 对于这个用例,是否有易于使用的 scalaz 替代品?如果不需要的话,我宁愿不打开潘多拉的盒子并引入 scalaz。
- 我不想使用 scalaz 的一个原因是,如果您像我一样不了解整个框架,那么真的很难弄清楚该怎么做。例如,使上述代码工作所需的隐式列表是什么?
import scalaz._
不知何故对我不起作用。[1]我如何从 API 文档中弄清楚这一点?
- 是否有更简洁的方式来表达验证用例?我一路跌跌撞撞,直到找到了可行的方法,但我不知道在 scalaz 中是否还有其他更好的方法来做同样的事情。
[1] 在大吃一惊之后,我得出了这组用于应用用例的导入。希望这对某人有所帮助:
import scalaz.std.string._
import scalaz.syntax.std.option._
import scalaz.syntax.apply._
import scalaz.Success
import scalaz.Failure
您可以通过定义辅助方法并使用 .apply
:
跳过 .tupled
步骤来更好地完成此操作
import scalaz._, Scalaz._
def lookup[K, V](m: Map[K, V], k: K, message: String): ValidationNel[String, V] =
m.get(k).toSuccess(NonEmptyList(message))
val validated: ValidationNel[String, HttpConnectionParams] = (
lookup(a, "url", "Url must be supplied") |@|
lookup(a, "username", "Username must be supplied") |@|
lookup(a, "password", "Password must be supplied")
)(HttpConnectionParams.apply)
还有,请不要羞于使用import scalaz._, Scalaz._
。我们都这样做,而且在绝大多数情况下都很好。您以后可以随时返回并优化您的导入。我也仍然支持 this answer 我多年前写的文章——你不应该觉得你需要对 Scalaz(或猫)有全面的了解才能有效地使用它。
背景
我有 Map[String,String]
个配置值。我想提取一系列密钥并在其中任何一个丢失时提供有意义的错误消息。例如:
val a = Map("url"->"http://example.com", "user"->"bob", "password"->"12345")
说我想把这个转化成一个案例class:
case class HttpConnectionParams(url:String, user:String, password: String)
现在,我可以简单地使用 for 循环来提取值:
for(url <- a.get("url");
user <- a.get("user");
password <- a.get("password")) yield {
HttpConnectionParams(url,user,password)
}
获得Option[HttpConnectionParams]
。这很好很干净,除非我得到 None
然后我不知道缺少什么。我想提供该信息。
使用 Scalaz 验证
进入scalaz。我使用的是 7.1.3 版本。
根据我能够整理的内容(一个很好的参考是 here)我可以使用析取:
for(url <- a.get("url") \/> "Url must be supplied";
user <- a.get("user") \/> "Username must be supplied";
password <- a.get("password") \/> "Password must be supplied") yield {
HttpConnectionParams(url,user,password)
}
这很好,因为现在我收到一条错误消息,但这是 railway oriented,因为它会在第一次失败时停止。如果我想得到所有的错误怎么办?让我们使用验证和应用程序构建器(又名“|@|”):
val result = a.get("url").toSuccess("Url must be supplied") |@|
a.get("username").toSuccess("Username must be supplied") |@|
a.get("password").toSuccess("Password must be supplied")
result.tupled match {
case Success((url,user,password)) => HttpConnectionParams(url,user,password)
case Failure(m) => println("There was a failure"+m)
}
问题
这符合我的预期,但我对用法有一些疑问:
- 对于这个用例,是否有易于使用的 scalaz 替代品?如果不需要的话,我宁愿不打开潘多拉的盒子并引入 scalaz。
- 我不想使用 scalaz 的一个原因是,如果您像我一样不了解整个框架,那么真的很难弄清楚该怎么做。例如,使上述代码工作所需的隐式列表是什么?
import scalaz._
不知何故对我不起作用。[1]我如何从 API 文档中弄清楚这一点? - 是否有更简洁的方式来表达验证用例?我一路跌跌撞撞,直到找到了可行的方法,但我不知道在 scalaz 中是否还有其他更好的方法来做同样的事情。
[1] 在大吃一惊之后,我得出了这组用于应用用例的导入。希望这对某人有所帮助:
import scalaz.std.string._
import scalaz.syntax.std.option._
import scalaz.syntax.apply._
import scalaz.Success
import scalaz.Failure
您可以通过定义辅助方法并使用 .apply
:
.tupled
步骤来更好地完成此操作
import scalaz._, Scalaz._
def lookup[K, V](m: Map[K, V], k: K, message: String): ValidationNel[String, V] =
m.get(k).toSuccess(NonEmptyList(message))
val validated: ValidationNel[String, HttpConnectionParams] = (
lookup(a, "url", "Url must be supplied") |@|
lookup(a, "username", "Username must be supplied") |@|
lookup(a, "password", "Password must be supplied")
)(HttpConnectionParams.apply)
还有,请不要羞于使用import scalaz._, Scalaz._
。我们都这样做,而且在绝大多数情况下都很好。您以后可以随时返回并优化您的导入。我也仍然支持 this answer 我多年前写的文章——你不应该觉得你需要对 Scalaz(或猫)有全面的了解才能有效地使用它。