2011-10-18 10 views
8

Mam dwie funkcje.Kompozycie za pomocą skalazy Strzałka?

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

    def applyDiscount(billable: Billable) : Billable 

Jak mogę komponować je tak, że mam jedną funkcję (DateTime, faktura, użytkownika, odniesienia) => (Akcja, iterable [rozliczanych])

Oto ubogich mans sposób co chcę

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

chcesz funkcję, która wykonuje pierwszy 'process' a następnie' applyDiscount'? –

+0

Tak, dokładnie. Czy te dwie funkcje można łączyć za pomocą strzałki skalarnej, a jeśli tak, to jaka jest składnia? – OleTraveler

Odpowiedz

9

Co masz (upraszczając) wynosi:

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

mogę myśleć kilka sposobów doin g to. Myślę, że moje preferencje to:

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

Albo też:

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

Jednak istnieje ewentualnie pointfree sposób - choć niekoniecznie tak, oczywiście

  • lift jest metoda na Function1W, która przenosi funkcję do królestwa funktora M
  • second to metoda na MAB których stosuje funkcję dół prawostronną stronie Bifunctor
  • :-> to metoda dostępna dla Bifunctors oznaczający zastosowanie funkcji na RHS.

EDIT - missingfaktor wydaje się być poprawne mówiąc f andThen g.lift[M].second prace:

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> 
+1

Być może 'f, a następnie g. Lift [M] .second'. – missingfaktor

+0

Ładnie destylowane, niesamowite, o ile jaśniejsze rzeczy są, kiedy można * tylko * zobaczyć typy! – retronym

+0

Niesamowita odpowiedź. Całkowicie rozumiem każdy krok tutaj po zabawie w repl. Stosując to do mojego problemu wpadłem na te dwa rozwiązania: val bfc = billableBuilder.fromContract (_: User, _: Contract, _: DateTime, _: Option [Order]): -> (applyDiscount (_)). Lift [Iterable] i val bfc = (applyDiscount (_)). Lift [Iterable] .second apply billableBuilder.fromContract (_: User, _: Contract, _: DateTime, _: Option [Order]) – OleTraveler

Powiązane problemy