2

型が [String, A] (A は複数の型) である一連の Yiher に対して一致を実行した後、左側の文字列をリストに蓄積したいと考えています。

(a, b, c, d, e) match {
  case (Right(a), Right(b), Right(c), Right(d), Right(e)) => {
    "All good, use a, b, c, d, and e!"
  }
  case anythingElse => {
    val strings = accLefts(anythingElse)
    doSomethingWithStrings(strings)
  }
}

タプルにしようとする.productIterator.toListと、List[Any] になってしまいます。失敗したケースを個別に処理すると (Rights と Lefts の組み合わせ)、指数関数的な数の case ステートメントが作成されます。

最後に List[Either[String, Any]] を取得して accLefts 呼び出しに渡すにはどうすればよいですか? それとも、試合以外のことをするべきでしたか?

4

3 に答える 3

5

これはまさにValidationNELScalaz(本質的に強化されたEitherもの)でサポートするように設計されている種類のものです。たとえば、Scalaz7を使用して次の設定があるとします。

import scalaz._, Scalaz._

case class Person(first: String, last: String, initial: Char, age: Int)

val first = "John".successNel[String]

val last = "Doe".successNel[String]
val badLast = "Empty last name".failureNel[String]

val initial = 'H'.successNel[String]
val badInitial = "Non-alphabetic MI".failureNel[Char]

val age = 45.successNel[String]
val badAge = "Negative age provided".failureNel[Int]

ここでは空でないリストNelを表し、これ は多かれ少なかれ、などと同等であることに注意してください。"John".successNel[String]Right("John"): Either[List[String], String]

これで、次のように書くことができます。

scala> println((first |@| last |@| initial |@| age)(Person.apply))
Success(Person(John,Doe,H,45))

または:

scala> println((first |@| badLast |@| initial |@| badAge)(Person.apply))
Failure(NonEmptyList(Empty last name, Negative age provided))

または:

scala> println((first |@| badLast |@| badInitial |@| badAge)(Person.apply))
Failure(NonEmptyList(Empty last name, Non-alphabetic MI, Negative age provided))

エラーは、の左側に蓄積されValidationNELます。詳細については、ここで私の答えを参照してください。

于 2013-03-01T21:14:39.657 に答える
3

おそらく、ネストされたパターンマッチングで?

case anythingElse => {
    val strings = anythingElse
                    .productIterator
                    .collect { case Left(str: String) => str }
                    .toList
    doSomethingWithStrings(strings)
}

str: Stringここでは型推論をガイドするためのものであるため、文字列には型がList[String]ないことに注意してください。List[Any]

于 2013-03-01T20:22:08.863 に答える
0

私はおそらく次のようなユーティリティ関数のセットを作成します

def fromTuple2[A, That](t: Tuple2[A,A])(implicit bf : CanBuildFrom[Nothing, A, That]): That =
  (bf.apply() += (t._1, t._2)).result();

必要なすべてのnタプルに対して。ボイラープレートコードはたくさんありますが、それは1回限りの作業です。そして、次のようなことができます。

val e1: Either[String,Int] = Right(3);
val e2: Either[String,String] = Left("3");
val test: List[Either[String,Any]] = fromTuple2(e1, e2);

おそらくより良いのは、次のようなエンリッチメントの暗黙的なメソッドを使用できることです。

implicit def fromTuple2Impl[A](t: Tuple2[A,A]) = new {
  def asCollection[That](implicit bf : CanBuildFrom[Nothing, A, That]): That =
    (bf.apply() += (t._1, t._2)).result();
}

ただ書くために

val test: List[Either[String,Any]] = (e1, e2).asCollection;

編集:タプルをsに拡張することもできます。これにより、フォールディングなどTraversableのすべてのメソッドが取得されます。toList

implicit def fromTuple2Impl3[A](t: Tuple2[A,A]) = new Traversable[A] {
  def asCollection[That](implicit bf : CanBuildFrom[Nothing, A, That]): That =
    (bf.apply() += (t._1, t._2)).result();
  override def foreach[U](f: (A) => U): Unit = {
    f(t._1); f(t._2);
  }
}

さらに作業を行うことで、さらに実装することができますIndexedSeq

于 2013-03-01T21:20:03.803 に答える