質問
把握のための=
を使用することはできます(セクション SLS の 6.19 :
オプション
いくつかの関数を持っているとします.GenagodicetagCode:
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)
.
すなわち、埋め込み発電機は、String => Option[Int]
呼び出しのシーケンスにmap
を注入する方法でした。これまでのところとても良い。
どちらか。rightprojection
実際に何をしたいのか: flatMap
monad を使用している前の例として、概要と同様の理解のために使用します。
しかし、私たちが同様のチェーンでそれを使うならば、今回はEither
Monad / Functorを使用していますが、それはうまくいきません:
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
^
.
問題には、右の投影がそのEither.RightProjection
メソッドの引数として予想される関数と関係がある(すなわち、それはflatMap
を期待する)。しかし、2番目の発電機でR => Either[L, R]
を呼び出さないように変更すると、まだコンパイルされません。
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)
^
.
Mega混入
しかし今、私は二重に混同します。以下は大丈夫です:
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 }
^
.
私はこれらが等価だと思った
- 何が起こっているの?
-
right
を介して=
ジェネレータを埋め込む方法は?
解決
把握用=
を埋め込むことができないという事実は、この問題 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 }}
.
SOの場合、y(b)
には、Either
が定義されていない結果型map
があります。
所属していません StackOverflow