天天看點

Scalaz(20)-Monad: Validation-Applicative版本的Either

  scalaz還提供了個type class叫validation。乍看起來跟\/沒什麼分别。實際上這個validation是在\/的基礎上增加了applicative功能,就是實作了ap函數。通過applicative執行個體就可以同時運算多個validation并傳回多條異常資訊。是以,\/與validation核心分别就在于validation可以傳回多條異常資訊。validation也是由兩種狀态組成:success和failure,分别與\/的left和right相對應。failure可以傳回多個值。我們先來看看validation在scalaz裡的定義:scalaz/validation.scala

與\/非常相似,也是提供了getorelse來擷取success[a]的a值。如果需要擷取failure[b]值則與\/一樣先用swap再用getorelse:

 validation的兩個狀态是這樣定義的:

validation也是一個monad,可以在for-comprehension中實作failure立即退出功能:

scalaz同樣為所有類型值提供了注入方法:scalaz.syntax/validationops.scala

上面的例子也可以這樣寫:

不過上面兩條異常資訊隻傳回了頭一條,這與\/并沒有什麼兩樣,因為它們的flatmap都是一樣的:

目前版本的scalaz已經放棄了flatmap用法:

因為validation又是個applicative。它實作了ap函數:

我們可以同時運算幾個validation算法并傳回所有異常資訊:

我們看到即使其中兩項運算出現異常但還是完成了所有運算并且傳回了兩條異常資訊。不過這兩條資訊合并在了string裡,可能不友善後續處理。validation注入方法提供了failurenel函數。我們試着用用:

現在這兩條資訊被放進了nonemptylist裡。nonemptylist就是一種list,不過沒有nil狀态。看看它的定義:scalaz/nonemptylist.scala

至少這個list含有head元素。nonemptylist的建構器在注入方法中:scalaz/nonemptylistops.scala

我們簡單地試用這個nonemptylist:

我們可以直接把它轉成list再進行處理操作。

繼續閱讀