2011-10-18 27 views
8

Tôi có hai chức năng.Composable sử dụng scalaz Arrow?

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

    def applyDiscount(billable: Billable) : Billable 

Làm thế nào tôi có thể soạn những cái mà tôi có một chức năng duy nhất của (DateTime, Invoice, Thành viên, tham khảo) => (Hành động, Iterable [Có thể thanh toán])

Đây là mans cách kém những gì tôi muốn

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

bạn muốn có một chức năng mà lần đầu tiên thực hiện 'process' và sau đó' applyDiscount'? –

+0

Vâng, chính xác. Hai hàm này có thể phối hợp bằng cách sử dụng mũi tên Scalaz và nếu có, cú pháp là gì? – OleTraveler

Trả lời

9

những gì bạn đã (đơn giản hóa) là:

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

tôi có thể nghĩ ra một số cách doin g này. Tôi nghĩ rằng sở thích của tôi là:

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

Hoặc thêm:

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

Tuy nhiên, có thể là một cách pointfree - mặc dù không nhất thiết phải như vậy, tất nhiên

  • lift là một phương pháp trên Function1W nâng chức năng vào lĩnh vực của functor M
  • second là phương pháp trên MAB áp dụng chức năng ở phía bên tay phải của Bifunctor
  • :-> là một phương pháp có sẵn cho Bifunctors biểu thị ứng dụng của hàm trên rh.

EDIT-missingfaktor dường như là đúng khi nói f andThen g.lift[M].second công trình:

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

Có lẽ 'f andThen g.lift [M] .second'. – missingfaktor

+0

Được chưng cất độc đáo, tuyệt vời bao nhiêu điều rõ ràng hơn khi bạn có thể * chỉ * xem các loại! – retronym

+0

Câu trả lời thú vị. Tôi hoàn toàn hiểu từng bước ở đây sau khi chơi xung quanh trong repl. Áp dụng điều này cho vấn đề của tôi Tôi đã đưa ra hai giải pháp sau: val bfc = billableBuilder.fromContract (_: Người dùng, _: Hợp đồng, _: DateTime, _: Option [Order]): -> (applyDiscount (_)). [Iterable] và val bfc = (applyDiscount (_)). Lift [Iterable] .second áp dụng billableBuilder.fromContract (_: User, _: Contract, _: DateTime, _: Option [Order]) – OleTraveler

Các vấn đề liên quan