天天看點

泛函程式設計(10)-異常處理-Either

  上節我們介紹了新的資料類型option:一個專門對付異常情況出現時可以有一緻反應所使用的資料類型。option可以使程式設計人員不必理會出現異常後應該如何處理結果,他隻是獲得了一個none值,但這個none值與他所期待的類型是一緻的,他可以繼續用處理這種類型資料的方法使用這個結果。不過遺憾的是我們通過none值隻能知道某個計算沒能得出結果,但到底發生了什麼事option并沒有提供任何提示。這樣我們也就無法向使用者提供貼切的系統錯誤或着操作失誤資訊了。

     這樣我們就需要在option的基礎上添加一個擴充功能的新資料類型,讓它可以傳回一些異常描述:either。可以想象either在傳回none的同時還要包含一個傳回值,用來描述異常。那麼這個none的形式就變成了none(e)了。我們先看看eigher的架構設計:

以上可見either需要處理兩個類型e和a:e代表異常類型,a代表計算類型。與option一樣,either也有兩種狀态:left代表無法完成計算,傳回值e是對異常情況的描述、right則代表計算正常完成,傳回計算結果a。從英文解釋,either不是right就是left。這種情況被稱為類型的“不聯合性”(disjoint union)。

提出了either的基本描述後開始資料類型操作函數的實作:

還是由于either這種類型的管子裡隻能存一個元素,是以操作函數的實作比較直接簡單:用類型比對和遞歸算法就行了。

在以下的函數中我們可以用一個函數 (a,b) => c 把兩個either[a],either[b]組合成either[c]:

考慮map2時并不複雜:由于我隻有一個利用低階的函數(a,b) =??? ,我必須想辦法把either管子裡的那個元素取出來計算完後塞到一個新的either管子裡去。以上我們已經實作了map,flatmap我們可以使用for comprehension來實作:

aa <- a: either - 從either管子取出元素

yield 産生新的either。map2_1是for comprehension的直接寫法。

由于我們有map和flatmap,我們可以試着用用either:

可以看出在以上三個動作中(age,name,salary)如果其中任何一個出現了異常left,結果就會是left了。

當然,我們還是有可能對一個系列的either類型值進行計算的,是以sequence,traverse這兩個函數總是會用到的:

來個實際點的例子:

mkperson輸入參數正确時傳回right。任何參數錯誤傳回left。不過如果兩個參數都是錯誤的話就隻能傳回其中一個提示資訊了。我們可以修改map2來擷取全部資訊:

注意:我們必須明确類型e為string,這樣才能把兩個資料接起來,因為我們不知道如何連接配接類型e。看看使用新版本後的結果:

沒錯,兩個資訊都連接配接起來傳回了。

繼續閱讀