Nest.JS | Monads -> รัฐ

Jan 27 2023
State monad เป็นแนวคิดการเขียนโปรแกรมเชิงฟังก์ชันที่ช่วยให้คุณจัดการสถานะในลักษณะที่ใช้งานได้และไม่เปลี่ยนรูป ช่วยให้คุณเขียนโค้ดที่อัปเดตสถานะของการคำนวณด้วยวิธีที่บริสุทธิ์และเรียบเรียงได้ ซึ่งทำให้ง่ายต่อการให้เหตุผลและทดสอบ

State monad เป็นแนวคิดการเขียนโปรแกรมเชิงฟังก์ชันที่ช่วยให้คุณจัดการสถานะในลักษณะที่ใช้งานได้และไม่เปลี่ยนรูป ช่วยให้คุณเขียนโค้ดที่อัปเดตสถานะของการคำนวณด้วยวิธีที่บริสุทธิ์และเรียบเรียงได้ ซึ่งทำให้ง่ายต่อการให้เหตุผลและทดสอบ

State monad มักถูกใช้เพื่อจัดการการคำนวณ stateful ในภาษาโปรแกรมเชิงฟังก์ชัน เช่น JavaScript monad สถานะช่วยให้คุณอธิบายการคำนวณที่อัปเดตสถานะบางอย่างด้วยวิธีที่บริสุทธิ์และเรียบเรียงได้ ซึ่งทำให้ง่ายต่อการให้เหตุผลเกี่ยวกับและทดสอบรหัสของคุณ

โดยทั่วไปแล้ว monad ของสถานะจะถูกนำไปใช้เป็นวัตถุที่มีเมธอดเดียว ซึ่งเรียกว่าrunซึ่งรับสถานะเริ่มต้นเป็นอินพุตและส่งกลับผลลัพธ์ของการคำนวณและสถานะที่อัปเดต สามารถใช้ State monad เพื่อเชื่อมโยงการคำนวณหลายรายการเข้าด้วยกันซึ่งอัปเดตสถานะเดียวกันและสร้างการคำนวณที่ซับซ้อนมากขึ้น

นี่คือตัวอย่างของ State monad ใน JavaScript:

class State {
  constructor(fn) {
    this.run = fn
  }
  map(f) {
    return new State((state) => {
        const [result, updatedState] = this.run(state);
        return [f(result), updatedState];
    });
  }
  chain(f) {
    return new State((state) => {
        const [result, updatedState] = this.run(state);
        return f(result).run(updatedState);
    });
  }
  // ...
}

ตัวอย่างเช่น คุณสามารถสร้างสถานะที่รับหมายเลขเริ่มต้นและส่งคืนหมายเลขใหม่โดยเพิ่มขึ้นทีละหนึ่ง จากนั้นคุณสามารถเชื่อมโยงหลายสถานะเหล่านี้เข้าด้วยกันเพื่อสร้างการคำนวณที่ซับซ้อนมากขึ้นซึ่งจะอัปเดตสถานะหลายครั้งโดยไม่ต้องส่งค่าด้วยตนเอง ระบุในแต่ละขั้นตอน

โปรดทราบว่า State Monad ไม่ใช่รูปแบบทั่วไปใน JavaScript ส่วนใหญ่จะใช้ในภาษาการเขียนโปรแกรมเชิงฟังก์ชัน เช่น Haskell, scala เป็นต้น

ตัวอย่างวิธีใช้StateMonad ใน Nest.js:

import { Injectable } from '@nestjs/common';
import { State, state } from 'fp-ts/lib/State';

interface StateType {
  counter: number;
}

@Injectable()
export class MyService {
  public incrementCounter(): State<StateType, number> {
    return state.get().map(s => s.counter + 1).put({ counter: s.counter + 1 });
  }

  public decrementCounter(): State<StateType, number> {
    return state.get().map(s => s.counter - 1).put({ counter: s.counter - 1 });
  }

  public getCounter(): State<StateType, number> {
    return state.get().map(s => s.counter);
  }
}

Monad Stateใช้เพื่อจัดการสถานะในลักษณะการทำงาน ตัวอย่างนี้ใช้ตัวนับอย่างง่ายเป็นสถานะ แต่สถานะอาจเป็นอะไรก็ได้ เช่น วัตถุหรืออาร์เรย์

เมธอดincrementCounter()เพิ่มตัวนับและอัปเดตสถานะdecrementCounter()เมธอดลดตัวนับและอัปเดตสถานะ เมธอดgetCounter()ส่งคืนค่าตัวนับปัจจุบัน

คุณสามารถเชื่อมโยงการคำนวณหลายรายการโดยใช้เมธอด.map(), .chain(),.ap()

const program: State<StateType, number> = myService
  .incrementCounter()
  .chain(() => myService.incrementCounter())
  .chain(() => myService.getCounter());

console.log(program.run({ counter: 0 }).value);

สิ่งสำคัญคือต้องสังเกตว่าตัวอย่างนี้เป็นเพียงตัวอย่างพื้นฐานและไม่ได้แสดงให้เห็นถึงพลังทั้งหมดของ Monads ในการเขียนโปรแกรมเชิงฟังก์ชัน Monads สามารถใช้เพื่อจัดการกรณีต่างๆ เช่น การจัดการข้อผิดพลาด การผูกมัดการคำนวณหลายรายการ และอื่นๆ คุณควรเข้าใจปัญหาและใช้กรณีต่างๆ ก่อนใช้ Monads

นอกจากนี้run()ต้องเรียกเมธอดเพื่อดำเนินการ State Monad และรับผลลัพธ์ โดยจะใช้สถานะเริ่มต้นเป็นอาร์กิวเมนต์

รายการชิ้นส่วน: