มีประเพณีไม่กี่:
PartialFunction
โปรดจำไว้ว่า a PartialFunction[A, B]
คือฟังก์ชันที่กำหนดไว้สำหรับโดเมนย่อยบางส่วนA
(ตามที่ระบุโดยisDefinedAt
วิธีการ) คุณสามารถ "ลิฟท์" ซึ่งเป็นเป็นPartialFunction[A, B]
Function[A, Option[B]]
นั่นคือฟังก์ชั่นที่กำหนดไว้ในช่วงทั้งของA
แต่มีค่าเป็นประเภทOption[B]
นี้จะกระทำโดยการภาวนาอย่างชัดเจนของวิธีการในlift
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)
วิธีการ
คุณสามารถ "ยก" การเรียกใช้เมธอดเป็นฟังก์ชัน สิ่งนี้เรียกว่าการขยายตัว (ขอบคุณ Ben James สำหรับเรื่องนี้) ตัวอย่างเช่น:
scala> def times2(i: Int) = i * 2
times2: (i: Int)Int
เรายกวิธีการให้เป็นฟังก์ชั่นโดยใช้เครื่องหมายขีดล่าง
scala> val f = times2 _
f: Int => Int = <function1>
scala> f(4)
res0: Int = 8
สังเกตความแตกต่างพื้นฐานระหว่างวิธีการและฟังก์ชั่น res0
เป็นตัวอย่าง (นั่นคือค่า ) ของประเภท (ฟังก์ชัน)(Int => Int)
functors
functor (ตามที่กำหนดโดยscalaz ) เป็นบางส่วน "ภาชนะ" (ผมใช้คำว่ามากคับ) F
เช่นว่าถ้าเรามีF[A]
และฟังก์ชั่นA => B
แล้วเราสามารถได้รับในมือของเราบนF[B]
(คิดว่าสำหรับตัวอย่างF = List
และmap
วิธีการ )
เราสามารถเข้ารหัสคุณสมบัตินี้ดังนี้
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
นี่คือ isomorphic ที่จะสามารถ "ยก" ฟังก์ชั่นA => B
เข้าไปในโดเมนของ functor นั่นคือ:
def lift[F[_]: Functor, A, B](f: A => B): F[A] => F[B]
นั่นคือถ้าF
เป็น functor และเรามีฟังก์ชั่นนี้เรามีฟังก์ชั่นA => B
F[A] => F[B]
คุณอาจลองใช้lift
วิธีนี้ - มันค่อนข้างเล็กน้อย
Monad Transformers
ในฐานะที่เป็นhcoopzกล่าวดังต่อไปนี้ (และฉันได้ตระหนักถึงเพียงว่าเรื่องนี้จะมีการบันทึกฉันจากการเขียนตันของรหัสที่ไม่จำเป็น) คำว่า "ลิฟท์" นอกจากนี้ยังมีความหมายภายในMonad หม้อแปลง จำได้ว่าหม้อแปลง monad เป็นวิธีหนึ่งของ "stacking" monads ที่อยู่ด้านบนของกันและกัน (monads ไม่ได้เขียน)
IO[Stream[A]]
ดังนั้นสำหรับตัวอย่างเช่นสมมติว่าคุณมีฟังก์ชั่นซึ่งจะส่งกลับอีกด้วย สามารถแปลงเป็นหม้อแปลงไฟฟ้า monad StreamT[IO, A]
ได้ ตอนนี้คุณอาจต้องการที่จะ "ยก" ค่าอื่นบางบางทีอาจจะว่ามันยังมีIO[B]
StreamT
คุณสามารถเขียนสิ่งนี้:
StreamT.fromStream(iob map (b => Stream(b)))
หรือสิ่งนี้:
iob.liftM[StreamT]
นี้ begs คำถาม: ทำไมฉันต้องการที่จะแปลงIO[B]
เป็นStreamT[IO, B]
? . คำตอบก็คือ "เพื่อใช้ประโยชน์จากความเป็นไปได้ในการแต่งเพลง" สมมติว่าคุณมีฟังก์ชั่นf: (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]