6

Scala 2.9.1 を使用して、次の 2 つのインスタンスを検討してEitherください。

scala> val er: Either[String, Int] = Right(1)
er: Either[String,Int] = Right(1)

scala> val el: Either[String, Int] = Left("a")
el: Either[String,Int] = Left(a)

leftand射影を使用することで、for 内包表記を使用できるのは素晴らしいことです (射影されrightた Both の偏ったモナドを介して):

scala> for { r <- er.right } yield r * 2
res6: Product with Either[String,Int] with Serializable = Right(2)

scala> for { r <- el.right } yield r * 2
res7: Product with Either[String,Int] with Serializable = Left(a)

filterメソッドがどちらかを返さないという決定が下された理由を誰かが私に説明できますか? 私は次のように動作することを期待していました:

scala> for { r <- er.right if r > 2 } yield r * 2 // r is NOT greater than 2!
res8: Product with Either[String,Int] with Serializable = Left(a)

代わりに、次のエラーが発生します: :9: エラー: 値 * は、Either[Nothing,Int] のメンバーではありません { r <- er.right if r > 2 } yield r * 2

基になる呼び出しがEither.RightProjection#filter実際に を返すようOptionです:

scala> er.right.filter(_ > 2)
res9: Option[Either[Nothing,Int]] = None

これは、少なくとも私が使用しようとしていた方法では、for-comprehension での if 句の使用を無効にします。

なぜこのデザインになったのか説明できる人はいますか?

4

1 に答える 1

12

要するにRight(b)、 があり、フィルター述語が失敗した場合、 に入れる値がないということLeftです。

Either[String, Int]のデフォルト値で失敗することにより、のケースで機能する実装を想像するかもしれませんLeft("")。Scala 標準ライブラリには、型の「空の」値を決定するモノイドなどの概念が含まれていないため、値を生成する機能がありません。

Scalazライブラリにはモノイド型クラス含まれており、バージョン 7 には右バイアスの分離型\/[A, B]( に同型Either[A, B])も含まれておりfilter、左の型がモノイドである場合にメソッドを持ちます。

scala> \/.right[String, Int](1).filter(_ > 2)
res1: scalaz.\/[String,Int] = -\/()

しかし、一般的なケースではこれを行うことはできませんEither[Nothing, Int]

于 2013-02-07T19:01:01.913 に答える