2015-06-28 42 views
6

Rozważ następujące łańcuchy funkcji, używając monadycznych pojęć dla zrozumienia.Monadyczne łańcuchy prób Scali z

for { 
    x <- List (11, 22, 33, 44, 55) 
    y <- f (x) 
    z <- g (y) 
    a <- h (z) 
    } yield a 

Jeśli f, g i h wszystkie mają ten podpis:

Int => Option [ Int ] 

następnie do-zrozumienia kompiluje grzywny. Jednak jeśli mam wymienić Option [ Int ] przez Try [ Int ], Scala typu inferencer narzeka linii

y <- f (x) 

z następującym komunikatem o błędzie.

error: type mismatch; 
    found : scala.util.Try[Int] 
    required: scala.collection.GenTraversableOnce[?] 
     y <- f (x) 

Dlaczego? Zarówno Option [ _ ], jak i Try [ _ ] są (lub powinny być) monadami i powinny działać płynnie, jak naszkicowane.

+1

Oto krótsza wersja 'for {x <- List (1,2,3); y <- Some (x)} yield y' jest w porządku, podczas gdy 'for {x <- List (1,2,3); y <- Spróbuj {x}} Wydajność y' powoduje wyżej wymieniony błąd. – Val

Odpowiedz

9

Możesz używać tylko monad tego samego rodzaju w celu zrozumienia. W tym przypadku wszystkie twoje wartości muszą być GenTraversableOnce, ponieważ pierwsza z nich jest. Działa z Option, ponieważ istnieje niejawna konwersja z Option na Seq, ale nie jest to możliwe dla Try.

+0

Dzięki. Gdybym chciał połączyć mój monadyczny styl obliczeń, ale również propagować komunikaty o błędach, jaka jest zalecana metoda Scala? –

+1

Powinieneś rzucić okiem na transformatory Monady. Polecam, abyś użył skalaza do tego. – drexin

+1

Jestem zaskoczony, że coś konceptualnie prostego, ponieważ łańcuchy monad powinny wymagać "ciężkiego sprzętu". –