目錄
PHP 2024 論壇
spO0q ?? ・ 10 月 13 日

PHP:單子

Nov 02, 2024 pm 09:09 PM

這篇文章的靈感很大程度上來自 Gina Banyard 在「FORUM PHP 2024」上的技術演講:

用 3 個簡單的同義詞揭開 Monad 的神秘面紗

讓我們從一些同義詞開始:

  • 容器
  • 包裝
  • 設計模式

如果你用谷歌搜尋“PHP monads”,其他概念會很快出現,例如函數式程式設計、綁定、堆疊,甚至深奧的數學(例如函子、廬半群)。

別怕。

從本質上講,Monad 是一種可以透過多種方式實現的模式。

設計模式

當您要執行一些操作時,您可以像往常一樣簡單地定義自訂物件和助理。

那麼,為什麼要費心考慮替代概念呢?

恕我直言,這仍然是一個好問題,因為您需要保持效率,但經典方法有常見的限制:

  • 操作順序很重要
  • 濕代碼
  • 例外

Monad 可以更一致地處理可選(或尚未可用)值。

Monad 與經典錯誤處理/異常

現代專案包含靜態分析工具,但 PHP 異常沒有類型化。

也就是說,工具無法偵測函數簽章中的異常,因此無法判斷程式碼是否正確處理異常。

為了測試這一點,開發團隊通常會編寫功能測試,但透過靜態分析進行早期檢測會更可靠。

來源:「Les Exception:le trou dans la raquette du typepage」(fr)

使用 Monads,您在所有情況下都會獲得一個類型化對象,例如自訂枚舉情況(例如 FileErrors::AccessDenied),因此錯誤會在系統中鍵入。

實作 Logger Monad

建立強大的日誌系統可能具有挑戰性。複製字串和呼叫很容易。

您可能會定義一個名為 log() 的自訂幫助程序,並在專案中的任何地方使用它,而不是對所有內容進行硬編碼。

這旨在保持程式碼乾燥,但可能不允許在特定情況下組合更複雜的函數。

函數式方法不包括使用這樣的全域幫助器。相反,它寧願實作一個 Monad 來包裝其他函數:

final class LoggerMonad {
    public function __construct(
        public mixed $data,
        public array $logs = [],
    ) {}

    public function bind(callable $fn) {
         $resultLoggerMonad = $fn($this->data);
         return new LoggerMonad(
             $resultLoggerMonad->data,
             [...$this->logs, ...$resultLoggerMonad->logs],
         );
   }
}

function loggify(callable $fn): Closure {
    return function ($value) use ($fn) {
        $name = (new ReflectionFunction($fn))->name;
        $log = [
            'Running '. $name .'('. var_export($value, true) .')'
        ];
        return new LoggerMonad($fn($value), $log);
    };
}
登入後複製
登入後複製

然後,您可以像這樣使用 loggify 包裝器:

function add2(int $v): int {
    return $v + 2;
}

function square(int $v): int {
    return $v * $v;
}

function multi3(int $v): int {
    return $v * 3;
}

function logIt($value, callable ...$fns) {
    $logging_fns = array_map(loggify(...), $fns);
    $monad = new LoggerMonad($value);
    foreach ($logging_fns as $fn) {
        $monad = $monad->bind($fn);
    }
    return $monad;
}

print_r(logIt(
   3,
   add2(...),
   square(...),
   multi3(...)
));
登入後複製

來源:“Monades simplement”,作者:Gina Banyard (fr)

什麼是綁定?

??寶貝別傷害我

Monad 旨在包裝值,可以是任何類型,包括物件和函數。

與任何其他包裝系統一樣,您會發現一個將此值作為輸入的構造函數(〜類)以及一些根據您嘗試實現的模式有其自己用途的方法。

但是,所有 Monad 都包含綁定函數。顧名思義,這是傳遞值(或回調)的地方。

無論這些回呼中發生什麼,monad 都會包裝它,這似乎是裝飾值和重構程式碼的強大方法。

程式碼可讀性更好嗎?

這顯然取決於實現,一開始很容易迷失。

但是,這種替代方法可以顯著減少 if 區塊的數量,並使回傳值更一致:

final class LoggerMonad {
    public function __construct(
        public mixed $data,
        public array $logs = [],
    ) {}

    public function bind(callable $fn) {
         $resultLoggerMonad = $fn($this->data);
         return new LoggerMonad(
             $resultLoggerMonad->data,
             [...$this->logs, ...$resultLoggerMonad->logs],
         );
   }
}

function loggify(callable $fn): Closure {
    return function ($value) use ($fn) {
        $name = (new ReflectionFunction($fn))->name;
        $log = [
            'Running '. $name .'('. var_export($value, true) .')'
        ];
        return new LoggerMonad($fn($value), $log);
    };
}
登入後複製
登入後複製

來源:fp4php - monad

優點和缺點

優點

  • ✅ 有不同用途的各種 monad : Maybe、Either、Logger、List、Reader 等
  • ✅ monad 允許使用更好的類型包裝程式碼,這可能會改善靜態分析
  • ✅ PHP 不為此提供內建構造,因此實作完全取決於開發人員

缺點

  • ❌ PHP 不為此提供內建結構(例如泛型),因此實作完全取決於開發人員
  • ❌它並沒有簡化程式碼

更進一步

  • 使用 monad、monad 轉換器和 Cats MTL 進行功能性錯誤處理
  • PHP 中的 Monad 和用法
  • PHP 函數式程式設計

包起來

希望您現在對 PHP monad 有更多了解。

當然,您不應該僅僅為了專案而添加花哨的設計模式。

此外,雖然這是一個全新的範例,但很容易錯過要點並專注於非常具體的方面,例如錯誤處理。

然而,發現新方法仍然令人耳目一新。我們需要跳出框框思考。

以上是PHP:單子的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱門文章

倉庫:如何復興隊友
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱門文章

倉庫:如何復興隊友
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱門文章標籤

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

11個最佳PHP URL縮短腳本(免費和高級) 11個最佳PHP URL縮短腳本(免費和高級) Mar 03, 2025 am 10:49 AM

11個最佳PHP URL縮短腳本(免費和高級)

在Laravel中使用Flash會話數據 在Laravel中使用Flash會話數據 Mar 12, 2025 pm 05:08 PM

在Laravel中使用Flash會話數據

簡化的HTTP響應在Laravel測試中模擬了 簡化的HTTP響應在Laravel測試中模擬了 Mar 12, 2025 pm 05:09 PM

簡化的HTTP響應在Laravel測試中模擬了

Instagram API簡介 Instagram API簡介 Mar 02, 2025 am 09:32 AM

Instagram API簡介

構建具有Laravel後端的React應用程序:第2部分,React 構建具有Laravel後端的React應用程序:第2部分,React Mar 04, 2025 am 09:33 AM

構建具有Laravel後端的React應用程序:第2部分,React

php中的捲曲:如何在REST API中使用PHP捲曲擴展 php中的捲曲:如何在REST API中使用PHP捲曲擴展 Mar 14, 2025 am 11:42 AM

php中的捲曲:如何在REST API中使用PHP捲曲擴展

在Codecanyon上的12個最佳PHP聊天腳本 在Codecanyon上的12個最佳PHP聊天腳本 Mar 13, 2025 pm 12:08 PM

在Codecanyon上的12個最佳PHP聊天腳本

宣布 2025 年 PHP 形勢調查 宣布 2025 年 PHP 形勢調查 Mar 03, 2025 pm 04:20 PM

宣布 2025 年 PHP 形勢調查

See all articles