1. 程式人生 > 其它 >fp-ts函數語言程式設計 - either, left & right

fp-ts函數語言程式設計 - either, left & right

前兩篇的快速連結
pipe與flow
option, map, flatten 與 chain

Either (fp-ts/lib/Either) 用來表示一個同步操作,該操作可能成功也可能失敗。TaskEither是Either的非同步版本,後面的隨筆再作介紹。
Right、Left是Either的衍生類(子類),分別表示成功(Right),失敗(Left)的情況。其定義可以近似認為如下:

type Either<E, A> = Left<E> | Right<A>

export interface Left<E> {
  readonly _tag: 'Left'
  readonly left: E
}

export interface Right<A> {
  readonly _tag: 'Right'
  readonly right: A
}

Either在函數語言程式設計中的主要作用是捕獲異常狀態,由於不能在pipe(管道)處理序列中加入try/catch,所以只能用Either來處理異常並中斷管道方法的執行。
下面的程式碼示例有兩個validate方法,驗證姓名、密碼。如果都通過,則執行最後的SayHello,否則後續方法不會被執行。

import { pipe } from "fp-ts/lib/function";
import { Either, left, right, chain, map} from "fp-ts/lib/Either";

type ErrorType =
  "invalid name"
  | "invalid password"
  | "others";

type UserInfo = {
    name: string,
    password: string,
    age?: number
}

function ValidateName(user: UserInfo): Either<ErrorType, UserInfo> {
    return  user.name.length > 3? right(user) : left("invalid name")
}
   
function ValidatePassword(user: UserInfo): Either<ErrorType, UserInfo> {
    return  user.password.length > 3? right(user) : left("invalid password")
}

function SayHello(user: UserInfo) {
    console.log(`hello ${user.name}`);
}

pipe(
    { name:'Andy', password:'123456'}, 
    ValidateName,  
    chain(ValidatePassword),
    map(SayHello)
);

pipe(
    { name:'Andy', password:'12'}, 
    ValidateName,  
    chain(ValidatePassword),
    map(SayHello)
);

使用ts-node命令執行後,會看到只有一行hello Andy的輸出。證明了第二個pipe,由於validate返回left,則中斷了後續程式碼的執行。

參考
https://dev.to/ryanleecode/practical-guide-to-fp-ts-p3-task-either-taskeither-2hpl
http://www.troikatech.com/blog/2020/09/24/fp-ts-error-handling-the-functional-way/