日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

2.4 zio入门——ZIO类型参数

發(fā)布時(shí)間:2024/3/13 编程问答 53 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2.4 zio入门——ZIO类型参数 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

2.4 ZIO類型參數(shù)

我們之前說(shuō)過(guò),類型 ZIO [R,E,A]的值是一種 functional effect,需要環(huán)境R,并且可能因E失敗或成功返回A。
現(xiàn)在,我們也了解了ZIO effect 成為并發(fā)工作流程的藍(lán)圖意味著什么,以及如何組合效果,下面讓我們?cè)敿?xì)討論每個(gè)ZIO類型參數(shù):

  • R是 effect 要執(zhí)行效果所需的環(huán)境。一般指的是 effect 需要的一些依賴關(guān)系,例如訪問(wèn)數(shù)據(jù)庫(kù)或日志記錄服務(wù),或者效果可能不需要任何環(huán)境,在這種情況下,類型參數(shù)將為Any。
  • E是效果可能失效的值的類型。這可能是Throwable或Exception,但也可能是特定領(lǐng)域的錯(cuò)誤類型,或者效果可能根本無(wú)法失敗,在這種情況下,type參數(shù)將為Nothing。
  • A是效果可以成功的值的類型。可以將其視為效果的返回值或輸出。
    理解這些類型參數(shù)的一種有用方法是將ZIO effect 想象為函數(shù)R => Either [E,A]。這并不是ZIO的實(shí)現(xiàn)方式(此定義不允許我們編寫(xiě)并發(fā),異步或資源安全的代碼
    算子),但這是一個(gè)有用的思維模型。

以下代碼段定義了這種 ZIO effect 的 toy model:

final case class ZIO[-R, +E, +A](run: R => Either[E, A])

從該定義可以看出,R參數(shù)是輸入(為了執(zhí)行效果,必須提供R類型的值),而E和A參數(shù)是輸出。 輸入被聲明為逆變的,而輸出被聲明為協(xié)變的。有關(guān) variance 的更詳細(xì)討論,請(qǐng)參見(jiàn)附錄。 否則,只要知道Scala variance注釋會(huì)改善類型推斷,這就是ZIO使用它們的原因。

讓我們看看如何使用這種思維模型來(lái)實(shí)現(xiàn)一些基本的構(gòu)造函數(shù)和運(yùn)算符:

final case class ZIO[-R, +E, +A](run: R => Either[E, A]) {self =>def map[B](f: A => B): ZIO[R, E, B] = ZIO(r => self.run(r).map(f))def flatMap[R1 <: R, E1 >: E, B](f: A => ZIO[R1, E1, B]): ZIO[R1, E1, B] = ZIO(r => self.run(r).fold(ZIO.fail(_), f).run(r)) }object ZIO {def effect[A](a: => A): ZIO[Any, Throwable, A] = ZIO(_ =>try Right(a)catch {case t: Throwable => Left(t)})def fail[E](e: => E): ZIO[Any, E, Nothing] = ZIO(_ => Left(e)) }

ZIO.effect方法將代碼塊包裝在一個(gè)effect中,將異常轉(zhuǎn)換為L(zhǎng)eft值,并將成功轉(zhuǎn)換為Right值。請(qǐng)注意,ZIO.effect的參數(shù)是按名稱命名的(使用 :=> 符號(hào)),這可以防止對(duì)代碼進(jìn)行急切的計(jì)算,從而允許ZIO創(chuàng)建描述執(zhí)行的值。
我們還實(shí)現(xiàn)了前面討論的flatMap運(yùn)算符,該運(yùn)算符使我們可以順序組合效果。 flatMap的實(shí)現(xiàn)如下:

  • 首先使用環(huán)境R1運(yùn)行原始效果,以生成Either [E,A]。
  • 如果原始效果因Left(e)失敗,它將立即以Left(e)返回此失敗。
  • 如果原始效果以Right(a)成功,它將在該a上調(diào)用f以產(chǎn)生新效果。然后,它將在所需的環(huán)境R1中運(yùn)行該新效果。
    如上所述,ZIO effect 實(shí)際上并不是這樣實(shí)現(xiàn)的,但是執(zhí)行一個(gè)效果,獲取其結(jié)果然后將其傳遞給下一個(gè)效果的基本思想是一個(gè)準(zhǔn)確的心理模型,它將幫助你在使用zio的過(guò)程中思考。
    我們將很快學(xué)習(xí)更多的方法來(lái)處理成功的ZIO值,但是現(xiàn)在讓我們著重研究錯(cuò)誤和環(huán)境類型,以建立其對(duì)他們的直覺(jué),因?yàn)樗麄兛赡懿荒敲粗庇^。
  • 2.4.1 錯(cuò)誤類型

    錯(cuò)誤類型表示效果潛在的失敗原因。 錯(cuò)誤類型很有用,因?yàn)樗试S我們使用類似 flatMap 這樣的運(yùn)算符來(lái)處理成功的返回值,同時(shí)將錯(cuò)誤處理推遲到更高級(jí)別。 這使我們能夠?qū)W⒂诔绦虻摹翱鞓?lè)之路”并在正確的地方處理錯(cuò)誤。
    例如,假設(shè)我們要編寫(xiě)一個(gè)簡(jiǎn)單的程序,該程序從用戶那里獲得兩個(gè)數(shù)字并將它們相乘:

    import zio._ lazy val readInt: ZIO[Any, NumberFormatException, Int] =??? lazy val readAndSumTwoInts: ZIO[Any, NumberFormatException, Int] = for {x <- readInty <- readInt } yield x * y

    請(qǐng)注意,readInt的返回類型為ZIO [Any,NumberFormatException,Int],指示它不需要任何環(huán)境,并且如果成功的話,可以返回整數(shù),如果失敗,則拋出NumberFormatException。
    錯(cuò)誤類型的第一個(gè)好處是,我們僅憑其簽名就知道該函數(shù)將如何失敗。我們對(duì)readInt的實(shí)現(xiàn)一無(wú)所知,但僅查看類型簽名,我們就知道它可能因NumberFormatException而失敗,也不會(huì)因任何其他錯(cuò)誤而失敗。這非常強(qiáng)大,因?yàn)槲覀兇_切知道潛在的錯(cuò)誤類型,而且我們永遠(yuǎn)不必借助“防御性編程”來(lái)處理未知錯(cuò)誤。第二個(gè)好處是,假設(shè)效果成功,我們就可以對(duì)效果結(jié)果進(jìn)行操作,將錯(cuò)誤處理推遲到以后。
    如果兩個(gè)readInt調(diào)用均失敗,并出現(xiàn)NumberFormatException,則readAndSumTwoInts也將失敗,并出現(xiàn)異常,并中止求和。此簿記將自動(dòng)為我們處理。我們可以直接將x和y相乘,而不必顯式地處理失敗的可能性。這將錯(cuò)誤處理邏輯推遲給調(diào)用方,后者可以重試,報(bào)告或推遲更高級(jí)別的處理。
    能夠了解效果可能如何失敗并將錯(cuò)誤推遲到應(yīng)用程序的更高級(jí)別很有用,但是在某些時(shí)候,我們需要能夠處理一些或所有錯(cuò)誤。

    要處理我們的ZIO玩具模型中的錯(cuò)誤,我們實(shí)現(xiàn)一個(gè)名為foldM的運(yùn)算符,如果原始效果失敗,它將使我們執(zhí)行一個(gè)效果,如果成功,則將執(zhí)行另一個(gè)操作:

    final case class ZIO [-R, +E, +A](run : R => Either [E, A]) {self =>def foldM [R1 <: R, E1, B](failure : E => ZIO [R1, E1, B],success : A => ZIO [R1, E1, B]) : ZIO [R1, E1, B] = ZIO(r => self.run(r).fold(failure, success).run(r))}

    實(shí)際上,該實(shí)現(xiàn)與我們上面介紹的flatMap非常相似。 我們只是使用failure函數(shù)在出現(xiàn)錯(cuò)誤的情況下返回新的效果,然后運(yùn)行該效果。
    錯(cuò)誤類型最有用的功能之一是能夠使指定效果完全不會(huì)失敗,這可能是因?yàn)橐呀?jīng)捕獲并處理了它的錯(cuò)誤。
    在ZIO中,我們通過(guò)指定Nothing作為錯(cuò)誤類型來(lái)做到這一點(diǎn)。 由于沒(méi)有Nothing類型的值,因此我們知道,如果我們有Either [Nothing,A],則它必須是Right。 我們可以使用它來(lái)實(shí)現(xiàn)錯(cuò)誤處理運(yùn)算符,這些運(yùn)算符可以讓我們靜態(tài)地證明效果不會(huì)因?yàn)槲覀円呀?jīng)處理了所有錯(cuò)誤而失敗。

    2.4.2 環(huán)境類型

    現(xiàn)在,我們對(duì)錯(cuò)誤類型有了一些印象,接下來(lái)讓我們關(guān)注環(huán)境類型。
    我們可以通過(guò)Any來(lái)為任何不需要環(huán)境的effect進(jìn)行建模。畢竟,如果effect需要類型為Any的值,則可以使用 ()(單位值),42或任何其他值來(lái)運(yùn)行效果。 因此,可以使用任何類型的值運(yùn)行的 effect 實(shí)際上是不需要任何特定類型環(huán)境的 effect。
    使用環(huán)境的兩個(gè)基本操作是訪問(wèn)環(huán)境(例如,獲得對(duì)數(shù)據(jù)庫(kù)的訪問(wèn)以執(zhí)行某些操作)和提供環(huán)境(在測(cè)試的時(shí)候提供測(cè)試環(huán)境,在生產(chǎn)的時(shí)候提供生產(chǎn)環(huán)境)。

    我們可以在ZIO的玩具模型中實(shí)現(xiàn)這一點(diǎn),如以下代碼片段所示:

    final case class ZIO[-R, +E, +A](run: R => Either[E, A]) {self =>def provide(r: R): ZIO[Any, E, A] = ZIO(_ => self.run(r))}object ZIO {def environment[R]: ZIO[R, Nothing, R] =ZIO(r => Right(r))}

    如您所見(jiàn),provider運(yùn)算符會(huì)返回不需要任何環(huán)境的新效果。 環(huán)境構(gòu)造函數(shù)使用所需的環(huán)境類型創(chuàng)建一個(gè)新效果,并將其作為成功值傳遞給環(huán)境。 這使我們可以訪問(wèn)環(huán)境并使用其他運(yùn)算符(例如map和flatMap)進(jìn)行處理。

    總結(jié)

    以上是生活随笔為你收集整理的2.4 zio入门——ZIO类型参数的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。