2015-09-02 25 views
6

Arkaplan

Map[String,String] yapılandırma değerlerine sahibim. Bir dizi anahtar çıkarmak ve bunlardan herhangi biri eksikse anlamlı hata mesajları vermek istiyorum.| @ | ile doğrulama kullanımı Scalaz içinde

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

Ben bir vaka sınıfında dönüştürdüğünü istediğini farz edelim: Örneğin:

for(url <- a.get("url"); 
    user <- a.get("user"); 
    password <- a.get("password")) yield { 
    HttpConnectionParams(url,user,password) 
} 

için: Şimdi

case class HttpConnectionParams(url:String, user:String, password: String) 

, ben sadece değerleri çıkarmak için bir for döngüsü kullanabilirsiniz Option[HttpConnectionParams] olsun. Bu güzel ve temiz, bir None olsun, o zaman neyin eksik olduğunu bilmiyorum. Bu bilgiyi vermek isterim.

Doğrulama

Scalaz

ile scalaz girin. 7.1.3 sürümünü kullanıyorum. Ben birlikte koymak mümkün kadarıyla

Ben kopukluklar kullanabilirsiniz (iyi bir referans here olduğunu):

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

şimdi bir hata mesajı almak için bu güzel, ama bu railway oriented olduğunu bunun nedeni ilk arızada durur. Ya tüm hataları almak istersem?

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

Sorular

Bu beklediğim yapar ama kullanımı hakkında bazı sorular var:

  • mi ("| | @" aka) onayını ve uygulamalı oluşturucu kullanalım Bu kullanım durumu için scalaz'a alternatif kullanımı kolay mı? Pandora'nın kutusunu açmayı ve mecbur kalmazsam scalaz yapmayı tercih ederim.
  • Scalaz'ı kullanmak istemememin bir nedeni, benim gibi tüm çerçeveyi bilmediğinizde ne yapacağınızı anlamak gerçekten çok zor olmasıdır. Örneğin, yukarıdaki kodu çalışmak için ihtiyacınız olan örtüklerin listesi nedir? import scalaz._ bir şekilde benim için çalışmadı. Bunu API dokümanlarından nasıl çözebilirim?
  • Doğrulama kullanım durumunu ifade etmenin daha özlü bir yolu var mı? Çalıştığım bir şeye gelene kadar yoluma düştüm ve scalazda aynı şeyi yapmanın diğer, daha iyi yolları olup olmadığına dair hiçbir fikrim yok.

[1] Çok fazla titizliğimden sonra, uygulama amaçlı kullanım için bu ithalat setine ulaştım. Bir yardımcı yöntemini tanımlayan ve .apply kullanarak .tupled atlayarak

import scalaz.std.string._ 
import scalaz.syntax.std.option._ 
import scalaz.syntax.apply._ 
import scalaz.Success 
import scalaz.Failure 
+0

"Scalaz'ı kullanmak istemememin bir nedeni, benim gibi tüm çerçeveyi bilmediğinizde ne yapacağınızı anlamak gerçekten çok zor" - Bunu doğrudan Tony'ye söylemem Morris;). Scalaz herkesin çayı olmayabilir; Eğer sert bir FP iknada değilseniz ve/veya Haskell'e aşina değilseniz (bu dilden çok ilham alırsa) anlamak için sarp bir öğrenme eğrisi vardır. Eğer onunla ne yapacağını biliyorsan, güçlü bir kütüphane var - onu vurduğun izlenimini alıyorum çünkü onu tam olarak öğrenmekten rahatsız olabilirsin - bu Scalaz'ın hatası değil –

+0

Scalaz'ın bir alternatifi Kediler. Scalaz topluluğunu, sahip olduğum her türlü konuda yardımcı olmaya hazır bulmuş olmamasına rağmen, belgelendirmeler ve örnekler açısından Scalaz'dan daha açık ve kullanıcı dostu olmak amaçlanıyor. –

+0

Evet, bir iş arkadaşınız Kedilere önerilir, ancak 0.2 sürümünde, insanların genel olarak kullanması için hazır mıdır? –

cevap

13

Sen güzel bu biraz daha fazlasını yapabilir: Umarım bu birileri yardımcı olur Ayrıca

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) 

, utanç olmayın lütfen import scalaz._, Scalaz._ kullanın. Hepimiz yaparız ve bu vakaların büyük çoğunluğunda iyidir. Her zaman geri dönebilir ve ithalatınızı daha sonra hassaslaştırabilirsiniz.Ben de yıllar önce yazdığım this answer'da bekliyorum - etkili parçaları kullanabilmek için Scalaz (veya kediler) hakkında kapsamlı bir anlayışa sahip olmanız gerektiğini hissetmemelisiniz.

+2

Sadece bunun ilk sorunuzun cevabı olmadığını fark ettiniz, ama şimdilik sağa yönelmiş bir hata yok. Standart kütüphanede ayırma türünü biriktirir, böylece kendi yuvarlamak istemediğiniz sürece, kediler veya Scalaz (veya Scalactic) en iyi bahistir. –

+0

Ve ben sormadan, boş olmayan liste sınıflarının (ValidationNel, vb.) Kullanımı olan bir soruyu yanıtladınız. Bu, takip eden herkes için çoklu hata mesajlarının basit bir şekilde birleştirilmesini önlemek içindir. Teşekkürler, bu oldukça yardımcı oldu. –