2016-06-08 1 views
3

내가 두 가지 기능 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> 쓸 수 :

답변

1

당신은을 사용할 수 있습니다 스카 파로부터의 Semigroup 타입 클라스의 연산 (|+|)을 결합한다.

기본 세미 그룹 Option은 콘텐츠의 세미 그룹을 사용하고 두 값이 모두있는 경우 값을 결합합니다. orElse 동작을 모방하려면 OptionTags.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와 함께 사용하기 위해, 당신은 어떤 방법으로 ListOption까지 암시 적 변환을 사용해야합니다. 그래서 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)(_)) 
+0

당신은 뭔가 더 관용적 인 것을 원했기 때문에이 대답은 약간 꺼진 것 같지만 기본 스 카즈/고양이를 사용하여 수행해야만하는 방법이라고 생각합니다. – Kolmar

+0

대답은 괜찮습니다.)) 이것은 내가 찾고있는 것입니다. – Michael

+0

@Michael'| + |'를'orElse'로 작동하도록 업데이트했습니다. – Kolmar

6

지금까지 내가 이런 식으로 뭔가가 표준 라이브러리에서 사용할 수 없습니다,하지만 당신은 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) 
+1

감사합니다 : 당신이 Option에 대한 암시 적 Monoid 인스턴스를 오버라이드 (override)하는 경우

xs flatMap (f(_)) 

당신은 또한 orElse|+| 작업을 할 수 있습니다. 'cats '또는 다른 3D 파티 라이브러리에서 사용할 수 있습니까? – Michael

+1

Foo. 약 1 분 만에 나를 때려. 그리고'foo'와'bar'에 대해서도 똑같은 정의가 있습니다. 유령 같은! Have a +1 :) –

관련 문제