Problemy pochodzi z val p = a*b
Jeśli piszesz prostszej
dla (a < - prawo (4) .right; b < - Prawo (5) .right) uzyskując a * b
go kompiluje i dostajesz właściwy wynik.
Twój problem ma dwie przyczyny
pierwsze, Either
występy map
i flatMap
nie mają zwykły podpis, a mianowicie do procedury map i flatMap zdefiniowane w ogólnej klasy M[A]
, (A => B) => M[B]
i (A => M[B]) => M[B]
. Procedura M[A]
jest zdefiniowana jako Either[A,B].RightProjection
, ale w wynikach i argumentach mamy Either[A,B]
, a nie rzut.
Po drugie, przetłumaczono sposób, w jaki val p = a*b
w celu zrozumienia. Scala odniesienia, 6,19 s 90:
generator P < - E a następnie wartości definicji p "e" jest przeliczeniu na poniższej generatora pary wartości, w którym X i 'są świeże nazwy :
(p,p′) <- for([email protected]<-e) yield {val x′@p′ = e′; (x,x′)}
Załóżmy uprościć kod tylko trochę, upuszczając a <-
. Ponadto, b
i zmieniono nazwę na p
i pp
na bliżej reguły przepisywania, z pp
dla. a
powinna być w zakresie dla (p < - prawy (5) .right; val s = A * p) dostarcza PP
zgodnie z reguły trzeba wymienić generator + definicji. Co się z tym wiąże, for(
i )yield pp
, bez zmian.
for((p, pp) <- for([email protected] <- Right(5).right) yield{val [email protected] = a*p; (x,xx)}) yield pp
Wewnętrzna dla jest przepisany do prostego mapie
for((p, pp) <- Right(5).right.map{case [email protected] => val [email protected] = a*p; (x,xx)}) yield pp
Tutaj jest problem. Right(5).right.map(...)
jest typu Either[Nothing, (Int,Int)]
, a nie Either.RightProjection[Nothing, (Int,Int)]
, jak byśmy chcieli. Nie działa na zewnątrz dla (który przekształca się w map
).Nie ma metody map
na Either
, jest ona zdefiniowana tylko na rzutach.
Jeśli przyjrzeć się dokładnie komunikatowi o błędzie, mówi tak, nawet jeśli wspomina o Product
i Serializable
, mówi, że jest to Either[Nothing, (Int, Int)]
i że nie ma na nim zdefiniowanej mapy. Para (Int, Int)
pochodzi bezpośrednio z reguły przepisywania.
Dla zrozumienia jest przeznaczony do pracy dobrze przy przestrzeganiu prawidłowego podpisu. Dzięki sztuczce z projekcjami Either
(która ma również swoje zalety), otrzymujemy ten problem.
Ach, to zaczyna mieć sens. Masz kilka literówek, które początkowo mnie potknęły (brakujące liczby pierwsze, delikatne błędy itp.), Które wkrótce sprzątnę. – srparish
Interesującym wynikiem powyższego jest to, że jeśli mam stałe monadyczne typy, wszystko będzie dobrze. Więc jeśli zależy mi tylko na właściwych projekcjach, mogę stworzyć niejawne, takie jak poniższe, które naprawia problem: implicit def RightProjection [A, B] (v: Albo [A, B]): Either.RightProjection [A, B] = v.right – srparish
Jeszcze raz wielkie dzięki za dokładny zapis! Przeczytałem odnośnik i wciąż nie wiedziałem, co się dzieje. Oczywiście w tym prostym przykładzie, a * b może być przeniesiony na wydajność, ale jeśli to jest zastąpione złożonym obliczeniem, które musi zostać przekazane do funkcji, która zwraca inną (albo powtórzyć to kilka razy), będąc w stanie użyć pośredniego przypisanie wartości może być znacznie czystsze, a następnie mieć wiele poziomów łańcuchów dla instrukcji/yield. – srparish