簡體   English   中英

使用| @ |進行驗證 在斯卡拉茲

[英]Validation usage with |@| in Scalaz

背景

我有配置值的Map[String,String] 我想提取一系列密鑰,並提供有意義的錯誤消息,如果缺少任何密鑰。 例如:

val a = Map("url"->"http://example.com", "user"->"bob", "password"->"12345")

假設我想將其轉換為案例類:

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版本。

從我能夠組合起來( 這里有一個很好的參考)我可以使用析取:

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) 
}

這很好,因為現在我收到一條錯誤信息,但這是鐵路導向的,因為它在第一次失敗時停止。 如果我想獲得所有錯誤怎么辦? 讓我們使用驗證和applicative builder(又名“| @ |”):

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步驟來.apply

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._ 我們都這樣做,在絕大多數情況下都很好。 您可以隨時返回並優化您的導入。 我還堅持多年前寫的這個答案 - 你不應該覺得你需要全面了解Scalaz(或貓)才能有效地使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM