Составляется с помощью скалаза Arrow? - PullRequest
8 голосов
/ 18 октября 2011

У меня есть две функции.

  def process(date: DateTime, invoice: Invoice, user: User, reference: Reference) : (Action, Iterable[Billable])

  def applyDiscount(billable: Billable) : Billable

Как их составить, чтобы у меня была одна функция (DateTime, Invoice, User, Reference) => (Action, Iterable [Billable]) *

Вот то, что я хочу, бедняга

  def buildFromInvoice(user: User, order: Invoice, placementDate: DateTime, reference: Reference) = {
    val ab = billableBuilder.fromInvoice(user, order, placementDate, reference)
    (ab._1, ab._2.map(applyDiscount(_))
  }

1 Ответ

9 голосов
/ 18 октября 2011

Что у вас есть (упрощение):

val f: A => (B, M[C]) //M is a Functor
val g: C => C

Я могу придумать несколько способов сделать это. Я думаю, что я предпочитаю:

(a: A) => g.lift[M].second apply f(a)

Или также:

(a: A) => f(a) :-> g.lift[M]  

Однако, возможно, существует pointfree способ - хотя и не обязательно, конечно,

  • lift - это метод на Function1W, который поднимает функцию в область функтора M
  • second - это метод MAB, который применяет функцию к правой стороне Bifunctor
  • :-> - метод, доступный для Bifunctors, обозначающий применение функции к rhs.

РЕДАКТИРОВАТЬ - отсутствующий фактор представляется правильным в высказывании f andThen g.lift[M].second работает:

scala> import scalaz._; import Scalaz._
import scalaz._
import Scalaz._

scala> case class A(); case class B(); case class C()
defined class A
defined class B
defined class C

scala> lazy val f: A => (B, List[C]) = sys.error("")
f: A => (B, List[C]) = <lazy>

scala> lazy val g: C => C = sys.error("")
g: C => C = <lazy>

Pointfree:

scala> lazy val h = f andThen g.lift[List].second
h: A => (B, List[C]) = <lazy>
...