昨天介紹了三條monad laws,構成monad的元素,只要滿足了就可以讓我們享受到monad的好處,而這些好處其實我們非常熟悉。
假設今天有一個需求,我們需要從第三方API取得所需的資料,因為有機會取得錯誤回應,所以方法回傳應該要是Either
var result = GetData()
.Match(
Success: x => x,
Fail: x => throw new Exception(x.Message));
async Task<Either> GetData()
{
using(var client = new HttpClient())
{
var url = "https://tcgbusfs.blob.core.windows.net/dotapp/youbike/v2/youbike_immediate.json";
try
{
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
return await Task.FromResult(Either.Right(result));
}
catch(Exception ex) return await Task.FromResult(Either.Left(ex));
}
}
如果回傳值是json,需要進行反序列化,而反序列化也有可能出錯,所以上面的程式就會變成
var result = GetData()
.Match(
Success: x => ConvertToEntity(x)
.Match(
Success: x => x,
Fail: x => throw new Exception(x.Message))),
Fail: x => throw new Exception(x.Message));
如果需要多次判斷,就會造成需要套嵌多層HOF,也就是我們說的回呼地獄,造成程式碼閱讀的困難。而Monad laws暗示了我們可以透過任意的組裝,把邏輯拆分增加可讀性。
var result = GetData()
.Bind(ConvertToEntity)
.Bind(GetFirstData)
.Match(
Success: x => x,
Fail: x => HandleException(x));
今天只是為了要延續解釋昨天的monad laws,寫到這邊我已經要沒哏了,應該感覺得出來我想到什麼就寫什麼,明天來重新介紹一下Task型別,後面預計介紹幾個其實常常在用但是沒有發現很FP的套件,這樣真的撐得完30天嗎?