Skip to content

Instantly share code, notes, and snippets.

@rirakkumya
Created May 18, 2012 12:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rirakkumya/2724922 to your computer and use it in GitHub Desktop.
Save rirakkumya/2724922 to your computer and use it in GitHub Desktop.
List[Either[Throwable,_]]のリスト中にLeftが1個以上あったら最初のLeftを返し、Leftが1個もなければ、Rightを1個のリストにまとめて返すコード
def f[a] = (d:List[Either[Throwable,a]]) =>
d.collect{case Left(x) => x}.headOption.toLeft(d.map{case Right(x) => x})
scala> Some(List(Right("4"),Right("3"))) map f
res11: Option[Product with Either[Throwable,List[java.lang.String]] with Serializable] = Some(Right(List(4, 3)))
scala> Some(List(Right("4"),Left(new RuntimeException),Right("3"))) map f
res12: Option[Product with Either[Throwable,List[java.lang.String]] with Serializable] = Some(Left(java.lang.RuntimeException))
scala> Some(List(Right("4"),Left(new RuntimeException("a")),Right("3"),Left(new RuntimeException("b")))) map f
res13: Option[Product with Either[Throwable,List[java.lang.String]] with Serializable] = Some(Left(java.lang.RuntimeException: a))
@ogatatsu
Copy link

fold使って書いてみますた

def f[A](d: List[Either[Throwable,A]]) = {
  d.foldRight[Either[Throwable, List[A]]](Right(Nil)) {
    case (Left(e) , _)           => Left(e)
    case (Right(_), Left(e))     => Left(e)
    case (Right(a), Right(list)) => Right(a :: list)
  }
}

@rirakkumya
Copy link
Author

なるほど。その手がありましたか。
とても読みやすいです。ありがとうございます!

@rirakkumya
Copy link
Author

しかもこれならEitherActionを使える。
EitherActionって名前どうにかしたい。

import EA._
def find(jStr:String) = EitherAction{
  jStr >>= parseJson >>= {
    _.foldRight[Either[Throwable, List[A]]](Right(Nil)) {
      case (Left(e) , _)           => BadRequest(e.getMessage) 異常
      case (Right(_), Left(e))     => BadRequest(e.getMessage) 異常
      case (Right(a), Right(list)) => (a :: list)              継続
    }
  } >>= findDb
}

ちなみに利用シチュエーションは、

["201201","201240"]

このようなデータがjsonで渡され、
パース実行時にエラーが発生する場合等。

@halcat0x15a
Copy link

遅レスですが、Scalazで。

scala> List(1.right[Throwable], 2.right[Throwable]).sequence[({ type X[A] = Either[Throwable, A] })#X, Int]
res1: Either[java.lang.Throwable,List[Int]] = Right(List(1, 2))

scala> List(1.right, (new Exception).left, (new Error).left).sequence[({ type X[A] = Either[Throwable, A] })#X, Int]
res2: Either[java.lang.Throwable,List[Int]] = Left(java.lang.Exception)

@rirakkumya
Copy link
Author

scalaz版ありがとうございます。勉強になります!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment