」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > JavaScript 函數式程式設計簡介:Do monad #12

JavaScript 函數式程式設計簡介:Do monad #12

發佈於2024-08-25
瀏覽:210

Introduction to Functional Programming in JavaScript: Do monads #12

在函數式程式設計中,monad 提供了一種以結構化和可預測的方式處理計算的方法。在各種 monad 中,Do Monad(也稱為「Do 表示法」或「Monad 理解」)是一個強大的構造,它允許對 Monad 操作進行更具可讀性和命令式的處理。

什麼是 Do Monad?

Do Monad 是一種語法糖,它允許您以類似於命令式程式設計的風格編寫單子操作序列,從而簡化單子的使用。 Do Monad 不是使用 .then 或 .flatMap 連結操作,而是讓您編寫更簡單易讀的程式碼。

Do Monad 的好處

  1. 可讀性:它允許以乾淨、線性的方式編寫複雜的單子操作。
  2. 命令式風格:提供一種以命令式程式設計所熟悉的風格來表達單子計算的方法。
  3. 錯誤處理:透過提供清晰一致的結構來簡化單元操作中錯誤的處理。

在 JavaScript 中實作 Do Monad

雖然 JavaScript 沒有像 Haskell 那樣內建對 Do Monad 的支持,但我們可以使用生成器函數和自訂運行器來實現類似的構造。

範例:實作 Do Monad Runner

讓我們先實作一個可以處理 Promise monad 的 Do Monad 運行程式。

function* doGenerator() {
  const a = yield Promise.resolve(1);
  const b = yield Promise.resolve(2);
  const c = yield Promise.resolve(a   b);
  return c;
}

function runDo(genFunc) {
  const iter = genFunc();

  function handle(result) {
    if (result.done) return Promise.resolve(result.value);
    return Promise.resolve(result.value).then(res => handle(iter.next(res)));
  }

  return handle(iter.next());
}

// Usage
runDo(doGenerator).then(result => console.log(result)); // 3

在此範例中,doGenerator 是一個產生 Promise 的生成器函數。 runDo 函數執行產生器,處理每個產生的 Promise 並將解析後的值傳回產生器。

Do Monad 的實際應用

Do Monad 可用於需要以可讀和可維護的方式對單子操作進行排序的各種場景。

範例:處理非同步操作

讓我們增強前面的範例以處理更複雜的非同步操作。

function* fetchUserData() {
  const user = yield fetch('https://api.example.com/user/1').then(res => res.json());
  const posts = yield fetch(`https://api.example.com/user/${user.id}/posts`).then(res => res.json());
  const firstPost = posts[0];
  const comments = yield fetch(`https://api.example.com/posts/${firstPost.id}/comments`).then(res => res.json());
  return { user, firstPost, comments };
}

runDo(fetchUserData).then(result => console.log(result));

在此範例中, fetchUserData 是一個生成器函數,它產生用於獲取使用者資料、他們的貼文以及第一篇貼文的評論的承諾。 runDo 函數以可讀且結構化的方式執行這些非同步操作。

範例:使用 Maybe Monad 處理可選值

我們也可以將 Do Monad 模式與其他 monad 一起使用,例如 Maybe。

class Maybe {
  constructor(value) {
    this.value = value;
  }

  static of(value) {
    return new Maybe(value);
  }

  map(fn) {
    return this.value === null || this.value === undefined ? Maybe.of(null) : Maybe.of(fn(this.value));
  }

  flatMap(fn) {
    return this.value === null || this.value === undefined ? Maybe.of(null) : fn(this.value);
  }
}

function* maybeDoGenerator() {
  const a = yield Maybe.of(1);
  const b = yield Maybe.of(2);
  const c = yield Maybe.of(a   b);
  return c;
}

function runMaybeDo(genFunc) {
  const iter = genFunc();

  function handle(result) {
    if (result.done) return Maybe.of(result.value);
    return result.value.flatMap(res => handle(iter.next(res)));
  }

  return handle(iter.next());
}

// Usage
const result = runMaybeDo(maybeDoGenerator);
console.log(result); // Maybe { value: 3 }

在此範例中,maybeDoGenerator 是與 Maybe monad 配合使用的生成器函數。 runMaybeDo 函數執行產生器,處理每個產生的 Maybe 值並將解包的值傳回產生器。

Do Monad 是一個強大的構造,它允許您以更具可讀性和命令性的風格編寫單子操作序列,從而簡化了單子的使用。透過實作 Do Monad 運行器,您可以以結構化且可維護的方式處理複雜的非同步操作、可選值和其他單子計算。

雖然 JavaScript 本身不支援 Do Monad 語法,但使用生成器函數和自訂運行器,您可以實現類似的功能。這種方法增強了程式碼的可讀性和可維護性,使函數式程式設計風格中的一元操作變得更容易。

版本聲明 本文轉載於:https://dev.to/francescoagati/introduction-to-functional-programming-in-javascript-do-monads-12-362a?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>
  • 小型機械手
    小型機械手
    小型機械手臂新重大發布 代碼已完全重構並編碼為屬性操作的新支援 這是一個操作範例: $classFile = \Small\ClassManipulator\ClassManipulator::fromProject(__DIR__ . '/../..') ->getC...
    程式設計 發佈於2024-11-06
  • 機器學習專案中有效的模型版本管理
    機器學習專案中有效的模型版本管理
    在机器学习 (ML) 项目中,最关键的组件之一是版本管理。与传统软件开发不同,管理机器学习项目不仅涉及源代码,还涉及随着时间的推移而演变的数据和模型。这就需要一个强大的系统来确保所有这些组件的同步和可追溯性,以管理实验、选择最佳模型并最终将其部署到生产中。在这篇博文中,我们将探索有效管理 ML 模型...
    程式設計 發佈於2024-11-06
  • 如何在 PHP 中保留鍵的同時按列值對關聯數組進行分組?
    如何在 PHP 中保留鍵的同時按列值對關聯數組進行分組?
    在保留鍵的同時按列值對關聯數組進行分組考慮一個關聯數組的數組,每個數組代表一個具有“id”等屬性的實體和“名字”。面臨的挑戰是根據特定列“id”對這些數組進行分組,同時保留原始鍵。 為了實現這一點,我們可以使用 PHP 的 foreach 迴圈來迭代陣列。對於每個內部數組,我們提取“id”值並將其用...
    程式設計 發佈於2024-11-06
  • 如何在 Gradle 中排除特定的傳遞依賴?
    如何在 Gradle 中排除特定的傳遞依賴?
    用Gradle 排除傳遞依賴在Gradle 中,使用應用程式外掛程式產生jar 檔案時,可能會遇到傳遞依賴,您可能想要排除。為此,可以使用排除方法。 排除的預設行為最初,嘗試排除 org.slf4j:slf4j- 的所有實例log4j12 使用以下程式碼:configurations { run...
    程式設計 發佈於2024-11-06
  • 極簡生活的藝術
    極簡生活的藝術
    什麼是極簡生活? 極簡生活是一種有意減少擁有的財產數量和生活中雜亂的生活方式。這不僅是為了整理您的空間,也是為了簡化您的生活,專注於真正重要的事情,並減少干擾。 為什麼採用極簡主義? 頭腦清晰:擁有的東西越少,需要擔心的事情就越少,頭腦就越清晰。 財務自由:透過...
    程式設計 發佈於2024-11-06
  • Java 混淆之謎
    Java 混淆之謎
    Come play with our Java Obfuscator & try to deobfuscate this output. The price is the free activation code! Obfuscated Java code Your goal...
    程式設計 發佈於2024-11-06
  • 如何在沒有圖像的 Outlook 電子郵件中建立圓角?
    如何在沒有圖像的 Outlook 電子郵件中建立圓角?
    在沒有圖像的 Outlook 中設定圓角樣式使用 CSS 在電子郵件用戶端中建立圓角可以非常簡單。但是,使用 CSS border-radius 屬性的傳統方法在 Microsoft Outlook 中不起作用。在設計具有圓角元素的電子郵件時,此限制提出了挑戰。 不用擔心,有一個解決方案可以讓您在 ...
    程式設計 發佈於2024-11-06
  • 如何在Python中高效比較字典中相等的鍵值對?
    如何在Python中高效比較字典中相等的鍵值對?
    比較字典是否相等的鍵值對在Python中,比較字典以檢查鍵值對是否相等是一項常見任務。一種方法是迭代字典並使用 zip 和 iteritems 方法比較每一對字典。然而,還有一些替代方法可以提供更好的程式碼優雅性。 其中一種方法是使用字典理解來建立僅包含共享鍵值對的新字典。代碼如下:shared_i...
    程式設計 發佈於2024-11-06
  • 如何在 PHP 中使用數組函數向左旋轉數組元素?
    如何在 PHP 中使用數組函數向左旋轉數組元素?
    在PHP 中向左旋轉數組元素在PHP 中旋轉數組,將第一個元素移動到最後一個元素並重新索引數組,可以使用PHP 的array_push() 和array_shift() 函數組合來實現。 PHP 函數:PHP 沒有專門用於旋轉的內建函數數組。但是,以下程式碼片段示範如何模擬所需的旋轉行為:$numb...
    程式設計 發佈於2024-11-06
  • 如何解決Java存取檔案時出現「系統找不到指定的路徑」錯誤?
    如何解決Java存取檔案時出現「系統找不到指定的路徑」錯誤?
    解決Java 中遇到「系統找不到指定的路徑」時的檔案路徑問題在Java 專案中,嘗試存取文字時遇到錯誤來自指定相對路徑的檔案。此錯誤是由於 java.io.File 類別無法定位指定路徑而產生的。 要解決此問題,建議從類別路徑中檢索文件,而不是依賴文件系統。透過這樣做,您可以消除相對路徑的需要,並確...
    程式設計 發佈於2024-11-06
  • Laravel 中的 defer() 函數如何運作?
    Laravel 中的 defer() 函數如何運作?
    Taylor Otwell 最近宣布了 Laravel 中的新函數 defer()。這只是對 defer() 函數如何運作以及使用它可能遇到的問題進行非常基本的概述。 找出問題 還記得您曾經需要從 API 獲取某些內容,然後在幕後執行一些用戶不關心但仍在等待的操作的路由嗎?是的,我們都至少經歷過一...
    程式設計 發佈於2024-11-06
  • 在 Python Notebook 中探索使用 PySpark、Pandas、DuckDB、Polars 和 DataFusion 的資料操作
    在 Python Notebook 中探索使用 PySpark、Pandas、DuckDB、Polars 和 DataFusion 的資料操作
    Apache Iceberg Crash Course: What is a Data Lakehouse and a Table Format? Free Copy of Apache Iceberg the Definitive Guide Free Apache Iceberg Crash ...
    程式設計 發佈於2024-11-06
  • Vue + Tailwind 和動態類
    Vue + Tailwind 和動態類
    我最近在做的一個專案使用了Vite、Vue和Tailwind。 使用自訂顏色一段時間後,我遇到了一些困惑。 在模板中添加和使用自訂顏色不是問題 - 使用 Tailwind 文件使該過程非常清晰 // tailwind.config.js module.exports = { theme:...
    程式設計 發佈於2024-11-06
  • 端對端(E 測試:綜合指南
    端對端(E 測試:綜合指南
    端到端测试简介 端到端(E2E)测试是软件开发生命周期的重要组成部分,确保整个应用程序流程从开始到结束都按预期运行。与专注于单个组件或几个模块之间交互的单元或集成测试不同,端到端测试从用户的角度验证整个系统。这种方法有助于识别应用程序不同部分交互时可能出现的任何问题,确保无缝且无错误的用户体验。 ...
    程式設計 發佈於2024-11-06
  • 可以在 Go 結構標籤中使用變數嗎?
    可以在 Go 結構標籤中使用變數嗎?
    在Go 結構體標籤中嵌入變數Go 的結構體標籤通常用於註釋和元數據,通常涉及簡單的字符串文字。但是,使用者可能會遇到在這些標籤中需要動態或計算值的情況。 考慮以下結構,其中帶有為 JSON 封送註解的「類型」欄位:type Shape struct { Type string `json:&...
    程式設計 發佈於2024-11-06

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3