2016-02-16 12 views
5

W ScalaZ, jaki jest idiomatyczny sposób konwersji Option[Validation[E, A]] na Validation[E, Option[A]]?Konwersja opcji [Weryfikacja [E, A]] na Walidację [E, Opcja [A]]

Na przykład w poniższym kodzie hipotetycznej:

def convert(x: Option[Validation[E, A]]): Validation[E, Option[A]] =  
    /* ??? */ 

def validateThing(thing: A): Validation[E, A] = 
    /* whatever */ 

def exampleUseCase(maybeThing: Option[Thing]): Validation[E, Option[Thing]] = { 
    val validated: Option[Validation[E, Thing]] = a.map(validateThing(_)) 

    // ... 

    val result: Validation[E, Option[Thing]] = convert(validated) 
    result 
} 

co by realizacja convert wyglądać w idiomatycznym ScalaZ?

+1

Powiedziałbym, że ta konwersja nie ma dla mnie większego sensu. Jakiego wyniku byś się spodziewał, gdyby "maybeThing" brzmiało "None"? Prawdopodobnie nie udało się sprawdzić poprawności, że nie ma, jeśli nie jest żadna, to możesz wyodrębnić wartość i umieścić ją jako "pomyślny" przypadek, wtedy nie potrzebujesz 'Opcji'. – 4lex1v

+0

'validate' i' validateThing' są hipotetyczne, tylko po to, aby pokazać kontekst miejsca, w którym taka konwersja * może * mieć miejsce. Interesuje mnie tylko to, czym będzie implementacja 'convert'. – kes

+0

Ale aby odpowiedzieć na konkretne pytanie, czego się spodziewać, gdy 'maybeThing' is' None': udana walidacja 'None'. – kes

Odpowiedz

4

Widzę tutaj dwa możliwe rozwiązania. Prawdopodobnie najprostszym użyciu dopasowania wzoru na argumencie, przykład:

def convert[A](v: Option[Validation[Throwable, A]]): Validation[Throwable, Option[A]] = { 
    v match { 
    case None => Validation.success(None) 
    case Some(valid) => valid.map(Some(_)) 
    } 
} 

Dla rozwiązania opartego Scalaz, myślałem o sequence, w ten sposób trzeba użyć ValidationNel zamiast walidacji agregować możliwych problemów, znajdują się poniżej wdrożenie convert z Traversable:

def convert[A](v: Option[ValidationNel[Throwable, A]]): ValidationNel[Throwable, Option[A]] = 
    Traverse[Option].sequenceU(v) 

Należy pamiętać, że w rzeczywistości używam sequenceU zamiast tylko sequence, to nic więcej niż wewnętrznej magii Scalaz do prawidłowego typu wnioskowania, bo Walidacja ma dwa parametry typu. Mam nadzieję, że pomoże

+2

Możesz po prostu napisać 'c.sequenceU' jeśli zaimportowałeś wszystko lub przynajmniej' std.option._' i 'syntax.traverse._'. –

Powiązane problemy