2017-12-12 2 views
2

の配列/リストを平らにはList[Validated[NonEmptyList[ErrorType], T]]であり、私は私の貧弱な試みはすべてのエラーを収集し、その後、新しいものを作ることですValidated[NonEmptyList[ErrorType], T]折りたたみ/私が持っているどのような猫cats.Validated

にこれを平らにしたいです。

val errors = validations collect { 
    case Invalid(errs) => errs.toList 
} 
if (errors.nonEmpty) Invalid(NonEmptyList.fromListUnsafe(errors.flatten)) else Valid(t) 

私はfoldMaptraverseを試みたが、私はスコープでMonoidを持っていない、と私は1つのライナーで、箱から出して、これを提供し、おそらく猫のように感じる問題に遭遇invarialby。

older answers on this kind of questionの中には期限が切れているものがあります(または、少なくとも私が参照している機能が見つかりません)。

更新:

私はこのタイプを修正しました。

+0

'cats._; cats.implicits._'は範囲内にありますか? –

+0

'cats.implicits._'はい。でも、私は平らにするために何をしていますか? – monkjack

+0

あなたの例で変数 't'の型を明確にすることができますか?これは単一の値( 'Option [T]'のようなもの)ですか?それは値の 'Seq [T]'ですか?後者の場合、 'T'型の値は返されますか?それは別のものですか? – SergGr

答えて

1

ご質問には、this example uses kind projector compiler plugin for partial application of type parametersとお答えください。 Scalaの用語にどれほど慣れ親しんでいるかによって、それは完全に意味をなさないかもしれません。基本的には、Scalaのメソッドの中には、特定の形状の引数が必要なものがあり、適切な場所に疑問符を追加することでコンパイラの助けが必要な場合があります。

また、インポートをいくつか追加してください。そして、与えられた

import cats._ 
import cats.data._ 
import cats.implicits._ 
import Validated.{ valid, invalid } 

val a = valid[String,Int](1) 
val as = List(a) 

あなたはValidated[E, List[T]]List[Validated[NonEmptyList[E, T]]]を変換するList.sequenceを使用することができます。この場合

as.sequence[Validated[String,?], Int] 

エラータイプとして単一の文字列を使用している場合、エラーの種類を表す文字列は、単一の文字列に一緒に連結されます。これは、 を言及したことからmonoidの制約が生じる場所です。文字列を文字列連結と組み合わせるのに役立ちます。エラータイプがStringではなくList[String]またはList[ErrorType]など、他のエラータイプも使用できます。あなたがエラーを蓄積したい場合には、何らかのエラーの種類のリストを使用して、リフト操作は文字列のリストに文字列から行くために上記必要とされている

res29: Validated[List[String], List[Int]] = Invalid(List("some")) 

val a = valid[List[String],Int](1) 
val b = invalid[List[String], Int]("some".lift[List]) 
List(a,b).sequence[Validated[List[String],?], Int] 

結果。

+0

包括的な答えをありがとう、間違ったタイプをタイプアウトしました。 'List [Validated [NonEmptyList [ErrorType]、T]]'だったはずです。混乱のために本当に申し訳ありません!とにかくupvoted。 – monkjack

1

あなたが使用することができます(これは、あなたがしなければならない)、sbt-partial-unificationまたは単に-Ypartial-unificationコンパイラフラグを使用している場合:

validation.sequence.map(_.head) 

これは安全ではない(検証のリストが空でなかった場合にのみ動作します)。 は今、あなたが最初のインスタンスを作成し、後でそれを検証する場合:

val t: T = ??? 

val validation: List[Validated[NonEmptyList[ErrorType], T]] = 
    List(checkQuantities, checkName, checkConsisteny).map(f => f(t)) 

そして、あなたはまだスコープでそれを持って、あなたはそれを直接提供することができます:

validation.sequence_.as(t) 
1

を私は文字通りちょうど似たに走りました昨日問題。これは、(私はスカラ座に2.12と猫1.1.0を使用しています)私はそれを解決する方法である:

import cats.Traverse 
import cats.data.{NonEmptyList, Validated} 

val list: List[Validated[NonEmptyList[ErrorType], T]] = ... 

import cats.instances.list._ 
val validated: Validated[NonEmptyList[ErrorType], List[T]] = Traverse[List].sequence(list) 

これはList[A]代わりのAに構造を平坦化されたとしてそれはあなたが望むものはかなりありません。 Aを同じタイプにフラット化するには、おそらくのどこかにcombineメソッドを実装する必要があります。

関連する問題