scala Even.RightProjection 혼란(설탕 제거 이해를 위해)
문제
나는 =
이해를 위한 스칼라(섹션에 지정된 대로) 6.19 SLS의) 다음과 같습니다.
옵션
어떤 기능이 있다고 가정 해 봅시다 String => Option[Int]
:
scala> def intOpt(s: String) = try { Some(s.toInt) } catch { case _ => None }
intOpt: (s: String)Option[Int]
그럼 이렇게 사용할 수 있어요
scala> for {
| str <- Option("1")
| i <- intOpt(str)
| val j = i + 10 //Note use of = in generator
| }
| yield j
res18: Option[Int] = Some(11)
이것이 본질적으로 다음과 동일하다는 것이 나의 이해였습니다.
scala> Option("1") flatMap { str => intOpt(str) } map { i => i + 10 } map { j => j }
res19: Option[Int] = Some(11)
즉, 임베디드 생성기는 map
일련의 flatMap
전화.여태까지는 그런대로 잘됐다.
어느쪽이든.오른쪽투영
내가 실제로 하고 싶은 일은: 이전 예제와 유사한 for-comprehension을 사용합니다. Either
모나드.
그러나 비슷한 체인에서 사용하지만 이번에는 Either.RightProjection
모나드/펑터, 작동하지 않습니다:
scala> def intEither(s: String): Either[Throwable, Int] =
| try { Right(s.toInt) } catch { case x => Left(x) }
intEither: (s: String)Either[Throwable,Int]
그런 다음 다음을 사용하십시오.
scala> for {
| str <- Option("1").toRight(new Throwable()).right
| i <- intEither(str).right //note the "right" projection is used
| val j = i + 10
| }
| yield j
<console>:17: error: value map is not a member of Product with Serializable with Either[java.lang.Throwable,(Int, Int)]
i <- intEither(str).right
^
문제는 오른쪽 투영이 인수로 기대하는 기능과 관련이 있습니다. flatMap
방법(예:그것은 기대한다 R => Either[L, R]
).하지만 전화하지 않도록 수정 right
두 번째 생성기에서는 여전히 컴파일되지 않습니다.
scala> for {
| str <- Option("1").toRight(new Throwable()).right
| i <- intEither(str) // no "right" projection
| val j = i + 10
| }
| yield j
<console>:17: error: value map is not a member of Either[Throwable,Int]
i <- intEither(str)
^
엄청난 혼란
하지만 이제 나는 두 배로 혼란스러워졌습니다.다음은 잘 작동합니다.
scala> for {
| x <- Right[Throwable, String]("1").right
| y <- Right[Throwable, String](x).right //note the "right" here
| } yield y.toInt
res39: Either[Throwable,Int] = Right(1)
하지만 다음은 그렇지 않습니다.
scala> Right[Throwable, String]("1").right flatMap { x => Right[Throwable, String](x).right } map { y => y.toInt }
<console>:14: error: type mismatch;
found : Either.RightProjection[Throwable,String]
required: Either[?,?]
Right[Throwable, String]("1").right flatMap { x => Right[Throwable, String](x).right } map { y => y.toInt }
^
나는 이것이 동등하다고 생각했다
- 무슨 일이야?
- 어떻게 삽입할 수 있나요?
=
전체에 대한 이해를 위한 생성기Either
?
해결책
삽입할 수 없다는 사실 =
이해를 위해 다음과 관련이 있습니다. 이 문제 Jason Zaugg가 보고함;해결책은 우편향이다 Either
(또는 그것과 동형인 새로운 데이터 유형을 생성합니다).
당신의 엄청난 혼란 때문에 설탕을 잘못 확장했습니다.디슈가링
for {
b <- x(a)
c <- y(b)
} yield z(c)
~이다
x(a) flatMap { b =>
y(b) map { c =>
z(c) }}
그리고는 아니다
x(a) flatMap { b => y(b)} map { c => z(c) }
따라서 다음을 수행했어야 합니다.
scala> Right[Throwable, String]("1").right flatMap { x => Right[Throwable, String](x).right map { y => y.toInt } }
res49: Either[Throwable,Int] = Right(1)
디슈가링에 대한 더 많은 재미(`j = i + 10` 문제)
for {
b <- x(a)
c <- y(b)
x1 = f1(b)
x2 = f2(b, x1)
...
xn = fn(.....)
d <- z(c, xn)
} yield w(d)
설탕이 탈당된다
x(a) flatMap { b =>
y(b) map { c =>
x1 = ..
...
xn = ..
(c, x1, .., xn)
} flatMap { (_c1, _x1, .., _xn) =>
z(_c1, _xn) map w }}
따라서 귀하의 경우에는 y(b)
결과 유형이 있음 Either
없는 것 map
한정된.