Scala 中的 Lift

Suraj P 2023年1月30日
  1. 將方法轉換為函式
  2. 在 Scala 中將純函式轉換為向量
  3. 在 Scala 中把部分函式轉化為函式
  4. Scala 中的 Monad 變形金剛
  5. まとめ
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 指的是類別之間的對映,有點像實體或物件的函式。例如,我們有類別 AB 以及將 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)
}

まとめ

在本文中,我們瞭解了提升的概念以及它在不同情況下的含義。以更可組合和更慣用的方式編寫程式碼非常有用,使我們能夠更多地關注程式碼的業務邏輯,而不是浪費時間構建程式碼的不同部分。

作者: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub