PHP: モナド

DDD
リリース: 2024-11-02 21:09:30
オリジナル
813 人が閲覧しました

この投稿は、「FORUM PHP 2024」での Gina Banyard による技術講演に大きく影響を受けています。

3 つの簡単な同義語でモナドをわかりやすく理解する

いくつかの同義語から始めましょう:

  • コンテナ
  • ラッパー
  • デザインパターン

「PHP モナド」で Google 検索すると、関数型プログラミング、バインディング、スタック、さらには難解な数学 (ファンクター、モノイドなど) など、他の概念がすぐに表示されます。

怖がらないでください。

本質的に、モナドはさまざまな方法で実装できるパターンです。

デザインパターン

実行する操作がある場合は、通常どおりカスタム オブジェクトとヘルパーを定義するだけで済みます。

それでは、なぜわざわざ別の概念を使うのでしょうか?

私見ですが、効率を維持する必要があるので、これはまだ良い質問ですが、古典的なアプローチには一般的な制限があります。

  • 操作の順序が重要です
  • WET コード
  • 例外

モナドはオプションの (またはまだ利用できない) 値をより一貫して処理できるようになります。

モナドと従来のエラー処理/例外の比較

最新のプロジェクトには静的分析用のツールが含まれていますが、PHP 例外は型指定されません。

言い換えると、ツールは関数シグネチャ内の例外を検出できないため、コードが例外を正しく処理しているかどうかを判断できません。

これをテストするために、開発チームは通常、機能テストを作成しますが、静的分析による早期検出の方が信頼性が高くなります。

出典: "Les Exception : le trou dans la raquette du typage" (fr)

モナドを使用すると、カスタム列挙型ケース (FileErrors::AccessDenied など) など、あらゆる場合に型付きオブジェクトを取得できるため、エラーはシステムに型付けされます。

ロガーモナドの実装

堅牢なログ システムを構築するのは困難な場合があります。文字列や呼び出しは簡単に複製できます。

すべてをハードコーディングする代わりに、log() というカスタム ヘルパーを定義し、プロジェクト内のあらゆる場所でそれを使用することになるでしょう。

これはコードを DRY に保つことを目的としていますが、特定のケースではより複雑な関数を作成できない可能性があります。

機能的なアプローチは、そのようなグローバル ヘルパーの使用では構成されません。代わりに、他の関数をラップするモナドを実装します:

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(...)
));
ログイン後にコピー

出典: Gina Banyard (fr) による「Monades simplement」

バインドとは何ですか?

??ベイビー、私を傷つけないでください

モナドは、オブジェクトや関数を含む任意の型の値をラップすることを目的としています。

他のラッピング システムと同様に、この値を入力として受け取るコンストラクター (~ クラス) と、実装しようとしているパターンに従って独自の目的を持つメソッドがいくつかあります。

ただし、すべてのモナドにはバインド関数が含まれています。名前が示すように、ここで値 (またはコールバック) が渡されます。

これらのコールバックで何が起こっても、モナドはそれをラップします。これは、値を装飾し、コードをリファクタリングするための強力な方法であると思われます。

コードは読みやすくなりましたか?

明らかに実装に依存しており、最初は迷いやすいです。

ただし、この代替アプローチでは、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 - モナド

長所と短所

長所

  • ✅ さまざまな目的に応じたさまざまなモナドがあります: たぶん、どちらか、ロガー、リスト、リーダーなど
  • ✅ モナドを使用すると、より良い型でコードをラッピングできるため、静的解析が改善される可能性があります
  • ✅ PHP はそのための組み込み構造を提供していないため、実装は完全に開発者次第です

短所

  • ❌ PHP はそのための組み込み構造 (ジェネリックなど) を提供していないため、実装は完全に開発者次第です
  • ❌ コードは単純化されません

さらに進む

  • モナド、モナド変換子、Cats MTL を使用した関数エラー処理
  • PHP でのモナドと使用法
  • PHP での関数型プログラミング

まとめ

PHP モナドについて少しは理解できたと思います。

もちろん、目的のためだけに派手なデザインパターンをプロジェクトに追加すべきではありません。

さらに、まったく新しいパラダイムであるにもかかわらず、要点を見逃して、エラー処理などの非常に特殊な側面に焦点を当ててしまうことがよくあります。

それでも、新しいアプローチを発見するのは新鮮です。私たちは既成概念にとらわれずに考える必要があります。

以上がPHP: モナドの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ソース:dev.to
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート