2015-12-31 12 views
8

と同様にEitherを扱うことはできますか? Optionには、getOrElseの機能があり、Eitherに返信します。LeftまたはプロセスRightに返信します。私はどのような定型句もなく、これを行う最速の方法を探しています:スカラどちらのマップ右または左へ左

val myEither:Either[String, Object] = Right(new Object()) 
myEither match { 
    case Left(leftValue) => value 
    case Right(righValue) => 
     "Success" 
} 

答えて

1

私はあなたが次のようにできると思います。

def foo(myEither: Either[String, Object]) = 
    myEither.right.map(rightValue => "Success") 
+0

'foo'のように見えますが、' Either'ではなく 'String'を返すべきです。最後に '.getOrElse(value)'がありませんか? – Marth

+0

「右または左に戻したいですか」は、正しい投影をマッピングすることによって行われます。 'A '、' B'の場合は 'A'(' B => A''を 'Right'とする)または' B''( 'A = Left')、あなたの友人は '.fold'です。 – cchantep

+0

あなたが正しいです、私はあまりにも迅速に質問を読んでいます。私はちょうどその中のコードを見て、 "これをもっと簡潔に書くにはどうすればよいか"という質問をしました。私の悪い。 – Marth

3

あなたは.fold使用することができます:それはあなたがLeftの値または別のものを返すようにしたいかどうか私には不明だ

再読み込みあなたの質問:

scala> val r: Either[Int, String] = Right("hello") 
r: Either[Int,String] = Right(hello) 

scala> r.fold(_ => "got a left", _ => "Success") 
res7: String = Success 

scala> val l: Either[Int, String] = Left(1) 
l: Either[Int,String] = Left(1) 

scala> l.fold(_ => "got a left", _ => "Success") 
res8: String = got a left 

編集を(別の場所で定義されています)
前者の場合、identityを​​、hoに渡すことができますweverこのAnyに戻り値の型を変更する場合があります:

scala> r.fold(identity, _ => "Success") 
res9: Any = Success 
4

両方cchantepさんとマルスのは、あなたの当面の問題に良い解決策です。しかし、より広義には、どちらかといえばOptionに完全に類似したものとして扱うことは困難です。特に、理解のために潜在的に有益な計算のシーケンスを表現させることは困難です。いずれも投影API(cchantepのソリューションで使用されています)を持っていますが、少し壊れています。 (いずれかの投影がガード、パターンマッチング、または変数の割り当てを含む解読のために中断しています)。

FWIW、私はこの問題を解決するためにlibraryと書いています。それはthis APIで補う。あなたはあなたのEithersに "バイアス"を定義します。 「右偏り」は、通常のフロー(マップ、取得など)がRightオブジェクトで表され、Leftオブジェクトが何らかの問題を表すことを意味します。 (右バイアスは従来のものですが、好きな場合は左バイアスを定義することもできますが)EitherOptionのように扱うことができます。完全に類似したAPIをオフラインにします。

import com.mchange.leftright.BiasedEither 

import BiasedEither.RightBias._ 

val myEither:Either[String, Object] = ... 
val o = myEither.getOrElse("Substitute") 

より有効に、あなたは今、すなわちflatMap、マップ、フィルタ、および内包のために使用し、どちらの真のScalaのモナドのように扱うことができます。すべての場合

val myEither : Either[String, Point] = ??? 
val nextEither = myEither.map(_.x) // Either[String,Int] 

または

val myEither : Either[String, Point] = ??? 
def findGalaxyAtPoint(p : Point) : Either[String,Galaxy] = ??? 

val locPopPair : Either[String, (Point, Long)] = { 
    for { 
    p <- myEither  
    g <- findGalaxyAtPoint(p) 
    } yield { 
    (p, g.population) 
    } 
} 

を処理手順は成功しました。locPopPairRight[Long]になります。何か問題が生じた場合は、最初にLeft[String]になります。

もう少し複雑ですが、空のトークンを定義することをお勧めします。テストp.x > 1000が失敗した場合に何が起こるか

val locPopPair : Either[String, (Point, Long)] = { 
    for { 
    p <- myEither  
    g <- findGalaxyAtPoint(p) if p.x > 1000 
    } yield { 
    (p, g.population) 
    } 
} 

:のは、上記の理解のために若干の変化を見てみましょうか? Leftは "空"を意味しますが、普遍的な適切な値はありません。LeftはすべてLeft[String]ではありません。今のところ、コードはNoSuchElementExceptionを投げることになるでしょう。しかし、我々は空のトークンに自分自身を指定することができ、以下のように:今

import com.mchange.leftright.BiasedEither 

val RightBias = BiasedEither.RightBias.withEmptyToken[String]("EMPTY") 
import RightBias._ 

val myEither : Either[String, Point] = ??? 
def findGalaxyAtPoint(p : Point) : Either[String,Galaxy] = ??? 

val locPopPair : Either[String, (Point, Long)] = { 
    for { 
    p <- myEither  
    g <- findGalaxyAtPoint(p) if p.x > 1000 
    } yield { 
    (p, g.population) 
    } 
} 

p.x > 1000テストが失敗した場合、例外は存在しません、locPopPairはちょうどLeft("EMPTY")になります。

関連する問題