내가 두 가지 기능 foo: Int => Option[Int]
및 bar: Int => Option[Int]
을 가지고 목록을 처리하는 데 사용할 가정?
3D 파티 라이브러리를 사용할 수 있습니다.orElse를 사용하여 Option을 반환하는 함수를 작성하는 방법은 무엇입니까?</p> <pre><code>val xs: List[Int] = ... xs flatMap {x => foo(x) orElse bar(x)} </code></pre> <p>내가 <code>xs flatMap (foo orElse bar)</code> 대신 <code>{x => foo(x) orElse bar(x)}</code> 쓸 수 :
답변
당신은을 사용할 수 있습니다 스카 파로부터의 Semigroup
타입 클라스의 연산 (|+|
)을 결합한다.
기본 세미 그룹 Option
은 콘텐츠의 세미 그룹을 사용하고 두 값이 모두있는 경우 값을 결합합니다. orElse
동작을 모방하려면 Option
을 Tags.FirstVal
태그로 묶어야합니다.
Tags.FirstVal
상태에 대한 문서 :
유형 태그 추가 할 첫 번째 피연산자를 선택하는
scalaz.Semigroup
인스턴스를 선택합니다.
당신은 포장 및 일부 F[T]
내부에서 유형 T
랩을 해제하려면 Tag
의 .subst
및 .unsubst
방법을 사용할 수 있습니다. 스칼라가 타입 유추를 조금 도와 주어야 할 것 같습니다. 모든 결합 기능에
모든는 다음과 같습니다
type F[T] = Int => Option[T]
val f = Tags.FirstVal.unsubst(
Tags.FirstVal.subst[F, Int](foo) |+|
Tags.FirstVal.subst[F, Int](bar))
그리고 flatMap
와 함께 사용하기 위해, 당신은 어떤 방법으로 List
에 Option
까지 암시 적 변환을 사용해야합니다. 그래서 flatMap
호출은 다음과 같을 수 있습니다
import scalaz._, Scalaz._
implicit val inst: Monoid[Option[Int]] =
Tags.First.unsubst(scalaz.std.option.optionFirst[Int])
val foo: Int => Option[Int] = x => if (x % 2 == 0) Some(x) else None
val bar: Int => Option[Int] = x => if (x % 3 == 0) Some(x) else None
val xs = List(1, 2, 3, 4, 5, 6, 7, 8)
xs.flatMap((foo |+| bar)(_))
지금까지 내가 이런 식으로 뭔가가 표준 라이브러리에서 사용할 수 없습니다,하지만 당신은 implicit class을 사용하여 직접 추가 할 수 있습니다 알고 :
implicit class WithOrElse[T, R](f: T => Option[R]) {
def orElse(g: T => Option[R])(x: T) = f(x) orElse g(x)
}
예 :
val foo: Int => Option[Int] = x => if (x % 2 == 0) Some(x) else None
val bar: Int => Option[Int] = x => if (x % 3 == 0) Some(x) else None
val xs = List(1, 2, 3, 4, 5, 6, 7, 8)
xs flatMap (foo orElse bar)
감사합니다 : 당신이 Option
에 대한 암시 적 Monoid
인스턴스를 오버라이드 (override)하는 경우
xs flatMap (f(_))
당신은 또한 orElse
로 |+|
작업을 할 수 있습니다. 'cats '또는 다른 3D 파티 라이브러리에서 사용할 수 있습니까? –
Michael
Foo. 약 1 분 만에 나를 때려. 그리고'foo'와'bar'에 대해서도 똑같은 정의가 있습니다. 유령 같은! Have a +1 :) –
당신은 뭔가 더 관용적 인 것을 원했기 때문에이 대답은 약간 꺼진 것 같지만 기본 스 카즈/고양이를 사용하여 수행해야만하는 방법이라고 생각합니다. – Kolmar
대답은 괜찮습니다.)) 이것은 내가 찾고있는 것입니다. – Michael
@Michael'| + |'를'orElse'로 작동하도록 업데이트했습니다. – Kolmar