Scala 中的 Lift
 
本文將討論 Scala 程式語言中的提升。提升有不同的含義;這取決於我們使用它的上下文。
讓我們一一看看。
將方法轉換為函式
我們有時會遇到想要將方法轉換為函式的情況。這是 Lift 的一個例子。
例如,假設我們有以下方法:
def mul(x: Int) = x*5
def isEven(x: Int) = x%2==0
現在,我們可以組合這些方法如下:
isEven(mul(4))
但如果我們想讓這種組合以函式的方式發生呢?那麼我們就必須將上述方法轉化為函式。
這可以通過使用 Scala 中的 _ 符號來提升它們來完成。
val mulAns = mul _
val isEvenAns = isEven _
現在,我們可以在功能上組合它們如下:
( mulAns andThen isEvenAns)(5)
完整的工作程式碼:
object MyClass {
    def mul(x: Int) = x*5
    def isEven(x: Int) = x%2==0
    def main(args: Array[String])
    {
        println(isEven(mul(4)));
        val mulAns = mul _
        val isEvenAns = isEven _
        println(( mulAns andThen isEvenAns)(5))
    }
}
輸出:
true
false
解釋:
第一個輸出是 true,因為 4 乘以 5,得到 20。這個 20 作為引數傳遞給 isEven 函式。
第二個輸出是 false,因為首先將 5 乘以 5,然後在 isEven 函式中檢查其結果。
在 Scala 中將純函式轉換為向量
Functor 指的是類別之間的對映,有點像實體或物件的函式。例如,我們有類別 A 和 B 以及將 A's 物件對映到 B's 物件的函子 F。
trait Functor[F[_]] {
    def mapping[A, B](X: F[A])(f: A => B): F[B]
    def lifting[A, B](f: A => B): F[A] => F[B] =
        X => map(X)(f)
}
在這種情況下,提升是指從 A=>B 中獲取一個函式並將其轉換為函子,使其成為 F[A] => F[B] 形式的函式。在使用巢狀資料型別時,這非常有用。
在 Scala 中把部分函式轉化為函式
在這種情況下,提升是指域的擴充套件。偏函式是可以應用於值的子域的函式。
但有時,我們可能想要擴充套件他們的領域,而提升幫助我們實現了這一目標。
假設我們有一個偏函式,它給出一個正數的平方根。
val sqrt: PartialFunction[Double, Double] =
{
    case temp if temp >= 0 => Math.sqrt(temp)
}
現在,我們可以使用 lift 方法擴充套件部分函式的域,使其看起來更優雅:
def getSqrtRootPartialFunction(t: Double) =
{
    sqrt.lift(t).map(ans => s"Square root of ${t} is ${ans}")
        .getOrElse(s"Cannot calculate square root for t")
}
完整的工作程式碼:
object MyClass {
     val sqrt: PartialFunction[Double, Double] = {
        case temp if temp >= 0 => Math.sqrt(temp)
    }
    def getSqrtRootPartialFunction(t: Double) = {
        sqrt.lift(t).map(ans => println(s"Square root of ${t} is ${ans}"))
           .getOrElse(println(s"Cannot calculate square root for t"))
    }
    def main(args: Array[String])
    {
        getSqrtRootPartialFunction(35)
    }
}
輸出:
Square root of 35.0 is 5.916079783099616
解釋:
所以,這裡對 sqrt 函式的提升所做的是將域從 PartialFunction[Double, Double] 擴充套件到 Function[Double, Option[Double]] 的整個雙精度域。
有時,提升部分函式用於避免 index out of bound 異常。
Seq("1", "2", "3").lift(1) // Some("2")
Seq("1", "2", "3").lift(7) // none returned
域已從 String 擴充套件到 Option[String]。因此,當我們嘗試訪問超出範圍的值時,提升的 Seq 返回 None 而不是丟擲 out of bound 異常。
Scala 中的 Monad 變形金剛
將 monad 組合在一起是使用 monad 轉換器完成的。假設我們有兩個 Futures:
val helloWorld: Future[Option[String]] = Future.successful(Some("hello world"))
val language: Future[String] = Future.successful("this is Scala language")
現在,由於兩個 Futures 具有不同的域,我們可以通過將 language 提升到 OptionT 來使用 monad 轉換器。這樣,我們可以以更一致的方式處理結果:
def MonadTransformer() = {
    val message: OptionT[Future, String] = for {
        hello <- OptionT(helloWorld)
        name  <- OptionT.liftF(language)
    } yield println(s"$hello $name")
    val result: Future[Option[String]] = message.value
    Await.result(result, 1 second)
}
まとめ
在本文中,我們瞭解了提升的概念以及它在不同情況下的含義。以更可組合和更慣用的方式編寫程式碼非常有用,使我們能夠更多地關注程式碼的業務邏輯,而不是浪費時間構建程式碼的不同部分。
