ログ日記

作業ログと日記とメモ

今更PHPでモナド的なものを書く

http://blog.dakatsuka.jp/2013/09/03/php-maybe-monad.html
この辺とか
http://d.hatena.ne.jp/kazu-yamamoto/20110413/1302683869
この辺とか見てたらちょっとやってみたくなったので。


○○言語でMonad実装って結構あるけど、MonadPlus使えないとあまり意味ないよね?的なところもある。


上記URLのTree探索するやつの

msearch :: MonadPlus m => (Int -> Bool) -> Tree -> m Int

これ、型推論、テンプレート、ジェネリクス、戻り値の型がないPHPでは無理目なので、コンテキスト(MonadPlus m)を引数として渡すことにする。
traitがあればreturnやmzeroを共通化できるので多少マシじゃないかな?と思いつつ。

<?php
    private function searchTree(Context $m, callable $f, Tree $tree)
    {
        if ($tree instanceof EmptyTree)
            return $m->mzero();
        if ($f($tree->value))
            return $this->searchTree($m, $f, $tree->left)
                        ->mplus($m->ret($tree->value))
                        ->mplus($this->searchTree($m, $f, $tree->right));
        else
            return $this->searchTree($m, $f, $tree->left)
                        ->mplus($this->searchTree($m, $f, $tree->right));
    }

    private function getTree()
    {
        $empty = new EmptyTree();
        return new Tree(3,
                        new Tree(2, $empty, $empty),
                        new Tree(1, $empty, $empty));
    }

    public function testTreeDataList()
    {
        $c = new DataListContext();
        $f = function($a){ return $a % 2 == 1; };
        $t = $this->getTree();
        $ret = $this->searchTree($c, $f, $t);
        $this->assertEquals(Cons::fromArray([3,1]), $ret);
    }
    public function testTreeMaybe()
    {
        $c = new MaybeContext();
        $f = function($a){ return $a % 2 == 1; };
        $t = $this->getTree();
        $ret = $this->searchTree($c, $f, $t);
        $this->assertEquals(new Just(3), $ret);
    }
https://github.com/nishimura/laiz-monad/blob/master/test/src/Laiz/Test/Monad/ContextTest.php

タイプ量が多い…。
traitってこういう使い方で良かったんだっけ?ファイルの置き場所とかセオリーが分からん。
composer.json置いてるけど未登録。