2017-12-12 1 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이없는 문제로 실행 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. 스칼라 용어에 얼마나 익숙한 지에 따라 그 의미가 완전하지 않을 수도 있습니다. 기본적으로 일부 스칼라 메서드는 특정 모양의 인수를 필요로하므로 적절한 위치에 물음표를 추가하여 컴파일러의 도움을 받아야합니다.

일부 가져 오기도 추가해야합니다. 그런 다음 주어진

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

,

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

당신은 List[Validated[NonEmptyList[E, T]]]Validated[E, List[T]] A를 변환 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

을 말 그대로 그냥 비슷한에 달렸다 어제 문제. 이것은 (I 스칼라 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 메소드를 구현하는 Monoid[A] 어딘가를 제공해야합니다.