PHP:單子
Nov 02, 2024 pm 09:09 PM這篇文章的靈感很大程度上來自 Gina Banyard 在「FORUM PHP 2024」上的技術演講:

PHP 2024 論壇
spO0q ?? ・ 10 月 13 日
用 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中文網其他相關文章!

熱門文章

熱門文章

熱門文章標籤

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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