pwm/treegami

View on GitHub
src/Tree.php

Summary

Maintainability
A
0 mins
Test Coverage
<?php
declare(strict_types=1);

namespace Pwm\Treegami;

use Closure;

final class Tree
{
    /** @var null|mixed */
    private $node;
    /** @var Tree[] */
    private $children;

    public function __construct($node = null, array $children = [])
    {
        $this->node = $node;
        $this->children = $children;
    }

    // (b -> (a, [b])) -> b -> Tree a
    public static function unfold(callable $f, $seed): Tree
    {
        $unfold = function (callable $f) use (&$unfold): Closure {
            return function ($seed) use (&$unfold, $f): Tree {
                [$node, $remaining] = $f($seed);
                return new Tree($node, \array_map($unfold($f), $remaining));
            };
        };
        [$node, $remaining] = $f($seed);
        return new Tree($node, \array_map($unfold($f), $remaining));
    }

    // (a -> [b] -> b) -> Tree a -> b
    public function fold(callable $f)
    {
        $fold = function (Tree $tree) use (&$fold, $f) {
            return $f($tree->node, \array_map($fold, $tree->children));
        };
        return $fold($this);
    }

    // (a -> b) -> Tree a -> Tree b
    public function map(callable $f): Tree
    {
        return $this->fold(function ($node, array $children) use ($f): Tree {
            return new Tree($f($node), $children);
        });
    }
}