Có một vài cách sử dụng:
Chức năng một phần
Hãy nhớ a PartialFunction[A, B]
là một hàm được định nghĩa cho một số tập hợp con của miền A
(như được chỉ định bởi isDefinedAt
phương thức). Bạn có thể "nâng" a PartialFunction[A, B]
thành a Function[A, Option[B]]
. Đó là, một chức năng được xác định trong toàn bộ của A
nhưng có giá trị là kiểuOption[B]
Điều này được thực hiện bằng cách gọi rõ ràng của phương thức lift
trên PartialFunction
.
scala> val pf: PartialFunction[Int, Boolean] = { case i if i > 0 => i % 2 == 0}
pf: PartialFunction[Int,Boolean] = <function1>
scala> pf.lift
res1: Int => Option[Boolean] = <function1>
scala> res1(-1)
res2: Option[Boolean] = None
scala> res1(1)
res3: Option[Boolean] = Some(false)
Phương pháp
Bạn có thể "nâng" một lời gọi phương thức thành một hàm. Điều này được gọi là mở rộng eta (cảm ơn Ben James vì điều này). Ví dụ:
scala> def times2(i: Int) = i * 2
times2: (i: Int)Int
Chúng tôi nâng một phương thức thành một hàm bằng cách áp dụng dấu gạch dưới
scala> val f = times2 _
f: Int => Int = <function1>
scala> f(4)
res0: Int = 8
Lưu ý sự khác biệt cơ bản giữa các phương thức và chức năng. res0
là một thể hiện (tức là nó là một giá trị ) của kiểu (hàm)(Int => Int)
Chức năng
Một functor (như được định nghĩa bởi scalaz ) là một số "container" (tôi sử dụng thuật ngữ cực kỳ lỏng lẻo), F
như vậy, nếu chúng ta có F[A]
một hàm và một hàm A => B
, thì chúng ta có thể chạm tay vào F[B]
(ví dụ, F = List
và map
phương thức )
Chúng tôi có thể mã hóa tài sản này như sau:
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
Đây là đẳng cấu để có thể "nâng" hàm A => B
vào miền của functor. Đó là:
def lift[F[_]: Functor, A, B](f: A => B): F[A] => F[B]
Đó là, nếu F
là một functor, và chúng ta có một chức năng A => B
, chúng ta có một chức năng F[A] => F[B]
. Bạn có thể thử và thực hiện lift
phương pháp - nó khá tầm thường.
Máy biến áp đơn nguyên
Như hcoopz nói dưới đây (và tôi vừa nhận ra rằng điều này sẽ giúp tôi tiết kiệm được việc viết một tấn mã không cần thiết), thuật ngữ "thang máy" cũng có ý nghĩa trong Monad Transformers . Hãy nhớ lại rằng một máy biến áp đơn nguyên là một cách "xếp chồng" các đơn nguyên lên nhau (các đơn nguyên không sáng tác).
Vì vậy, ví dụ, giả sử bạn có một hàm trả về một IO[Stream[A]]
. Điều này có thể được chuyển đổi để biến áp đơn nguyên StreamT[IO, A]
. Bây giờ bạn có thể muốn "nâng" một số giá trị khác IO[B]
có lẽ nó cũng là một StreamT
. Bạn có thể viết cái này:
StreamT.fromStream(iob map (b => Stream(b)))
Hoặc này:
iob.liftM[StreamT]
Điều này đặt ra câu hỏi: tại sao tôi muốn chuyển đổi IO[B]
thành một StreamT[IO, B]
? . Câu trả lời sẽ là "tận dụng các khả năng sáng tác". Giả sử bạn có một chức năngf: (A, B) => C
lazy val f: (A, B) => C = ???
val cs =
for {
a <- as //as is a StreamT[IO, A]
b <- bs.liftM[StreamT] //bs was just an IO[B]
}
yield f(a, b)
cs.toStream //is a Stream[IO[C]], cs was a StreamT[IO, C]