我們之前說過,型別zio [r,e,a]
的值是一種 functional effect,需要環境r,並且可能因e失敗或成功返回a。
現在,我們也了解了zio effect 成為併發工作流程的藍圖意味著什麼,以及如何組合效果,下面讓我們詳細討論每個zio型別引數:
以下**段定義了這種 zio effect 的 toy model:
final
case
class zio[
-r,+e,
+a](run: r => either[e, a]
)
從該定義可以看出,r引數是輸入(為了執行效果,必須提供r型別的值),而e和a引數是輸出。 輸入被宣告為逆變的,而輸出被宣告為協變的。有關 variance 的更詳細討論,請參見附錄。 否則,只要知道scala variance注釋會改善型別推斷,這就是zio使用它們的原因。
讓我們看看如何使用這種思維模型來實現一些基本的建構函式和運算子:
final
case
class zio[
-r,+e,
+a](run: r => either[e, a]
)object zio
)def fail[e]
(e:=> e)
: zio[
any, e,
nothing
]= zio(_ => left(e)
)}
zio.effect方法將**塊包裝在乙個effect中,將異常轉換為left值,並將成功轉換為right值。請注意,zio.effect的引數是按名稱命名的(使用 :=> 符號),這可以防止對**進行急切的計算,從而允許zio建立描述執行的值。
我們還實現了前面討論的flatmap運算子,該運算子使我們可以順序組合效果。 flatmap的實現如下:
首先使用環境r1執行原始效果,以生成either [e,a]
。
如果原始效果因left(e)失敗,它將立即以left(e)返回此失敗。
如果原始效果以right(a)成功,它將在該a上呼叫f以產生新效果。然後,它將在所需的環境r1中執行該新效果。
如上所述,zio effect 實際上並不是這樣實現的,但是執行乙個效果,獲取其結果然後將其傳遞給下乙個效果的基本思想是乙個準確的心理模型,它將幫助你在使用zio的過程中思考。
我們將很快學習更多的方法來處理成功的zio值,但是現在讓我們著重研究錯誤和環境型別,以建立其對他們的直覺,因為他們可能不那麼直觀。
錯誤型別表示效果潛在的失敗原因。 錯誤型別很有用,因為它允許我們使用類似 flatmap 這樣的運算子來處理成功的返回值,同時將錯誤處理推遲到更高階別。 這使我們能夠專注於程式的「快樂之路」並在正確的地方處理錯誤。
例如,假設我們要編寫乙個簡單的程式,該程式從使用者那裡獲得兩個數字並將它們相乘:
import zio._
lazy
val readint: zio[
any, numberformatexception,
int]=?
??lazy
val readandsumtwoints: zio[
any, numberformatexception,
int]
=for
yield x * y
請注意,readint的返回型別為zio [any,numberformatexception,int]
,指示它不需要任何環境,並且如果成功的話,可以返回整數,如果失敗,則丟擲numberformatexception。
錯誤型別的第乙個好處是,我們僅憑其簽名就知道該函式將如何失敗。我們對readint的實現一無所知,但僅檢視型別簽名,我們就知道它可能因numberformatexception而失敗,也不會因任何其他錯誤而失敗。這非常強大,因為我們確切知道潛在的錯誤型別,而且我們永遠不必借助「防禦性程式設計」來處理未知錯誤。第二個好處是,假設效果成功,我們就可以對效果結果進行操作,將錯誤處理推遲到以後。
如果兩個readint呼叫均失敗,並出現numberformatexception,則readandsumtwoints也將失敗,並出現異常,並中止求和。此簿記將自動為我們處理。我們可以直接將x和y相乘,而不必顯式地處理失敗的可能性。這將錯誤處理邏輯推遲給呼叫方,後者可以重試,報告或推遲更高階別的處理。
能夠了解效果可能如何失敗並將錯誤推遲到應用程式的更高階別很有用,但是在某些時候,我們需要能夠處理一些或所有錯誤。
要處理我們的zio玩具模型中的錯誤,我們實現乙個名為foldm的運算子,如果原始效果失敗,它將使我們執行乙個效果,如果成功,則將執行另乙個操作:
final case class zio [-r, +e, +a](run : r => either [e, a])
實際上,該實現與我們上面介紹的flatmap非常相似。 我們只是使用failure函式在出現錯誤的情況下返回新的效果,然後執行該效果。
錯誤型別最有用的功能之一是能夠使指定效果完全不會失敗,這可能是因為已經捕獲並處理了它的錯誤。
在zio中,我們通過指定nothing作為錯誤型別來做到這一點。 由於沒有nothing型別的值,因此我們知道,如果我們有either [nothing,a]
,則它必須是right。 我們可以使用它來實現錯誤處理運算子,這些運算子可以讓我們靜態地證明效果不會因為我們已經處理了所有錯誤而失敗。
現在,我們對錯誤型別有了一些印象,接下來讓我們關注環境型別。
我們可以通過any來為任何不需要環境的effect進行建模。畢竟,如果effect需要型別為any的值,則可以使用()
(單位值),42或任何其他值來執行效果。 因此,可以使用任何型別的值執行的 effect 實際上是不需要任何特定型別環境的 effect。
使用環境的兩個基本操作是訪問環境(例如,獲得對資料庫的訪問以執行某些操作)和提供環境(在測試的時候提供測試環境,在生產的時候提供生產環境)。
我們可以在zio的玩具模型中實現這一點,如以下**片段所示:
final
case
class zio[
-r,+e,
+a](run: r => either[e, a]
)object zio
如您所見,provider運算子會返回不需要任何環境的新效果。 環境建構函式使用所需的環境型別建立乙個新效果,並將其作為成功值傳遞給環境。 這使我們可以訪問環境並使用其他運算子(例如map和flatmap)進行處理。 2 2 zio入門 按順序組合ZIO
正如上小節所述,zio效果是描述併發工作流的藍圖,並且我們通過轉換和組合更小,更簡單的效果來構建更複雜的效果,從而解決業務問題。我們看到了如何使用 zio 的 delay 運算子將乙個效果轉換為另一種效果,並將其執行延遲到將來。除了延遲之外,zio還擁有數十種其他強大的運算子,它們可以轉換並組合效果...
南陽OJ 語言入門 24
時間限制 3000 ms 記憶體限制 65535 kb 難度 2 描述 現在給出你一些數,要求你寫出乙個程式,輸出這些整數相鄰最近的素數,並輸出其相距長度。如果左右有等距離長度素數,則輸出左側的值及相應距離。如果輸入的整數本身就是素數,則輸出該素數本身,距離輸出0 輸入第一行給出測試資料組數n 0輸...
VC下的ADO程式設計入門 2 4
好了,現在我們正式進入本主題,let s go n新建乙個基於對話的應用程式 zjy,在對話方塊上新增乙個按鈕和列表控制項,並把列表控制項的樣式設定為報表檢視,還有用 classwizard 給列表控制項新增乙個控制項變數 m list n在 stdafx.h 標頭檔案中新增一條如下語句 impor...