php-fp/php-fp-combinators

此包已被废弃,不再维护。未建议替代包。

PHP中的一些函数组合子。

dev-master 2016-06-13 00:00 UTC

This package is not auto-updated.

Last update: 2023-06-05 08:43:40 UTC


README

简介

组合子是一些简单的函数,允许您在创建后修改值和函数的行为。这些允许更高效地重用函数并减少样板代码。

API

默认情况下,这些组合子不是完全柯里化的,主要是为了优化原因,但它们设计得足以满足大多数常见用例。因此,类型签名使用逗号(,)来表示多个参数。

compose :: (b -> c), (a -> b) -> a -> c

而不是编写function ($x) { return f(g(x)); }compose允许我们将其表示为compose('f', 'g')(其中参数可以是闭包、可调用对象或任何可以用作“函数”的东西)。给定两个函数,fg,将返回一个函数,该函数接受一个值,x,并返回f(g(x))。此操作是结合律的,因此compose调用可以嵌套以创建更长的函数链。这里有一个简单的、两个函数的示例

<?php

use PhpFp\Combinators as F;

$strictUcFirst = F::compose('ucfirst', 'strtolower');
$strictUcFirst('HELLO, WORLD'); // Hello, world

请注意,函数是按照从左到右的顺序调用的。如果需要相反的顺序,这可以很容易地实现

<?php

use PhpFp\Combinators as F;

// The `flip` function is discussed later in this document.
$pipe = flip(F::compose());
$pipe($f, $g)($x) === $g($f($x));

flip :: (a, b -> c) -> (b, a) -> c

此函数接受一个接受两个参数的函数,并返回相同功能的函数,但参数顺序被交换

<?php

use PhpFp\Combinators as F;

$divide = function ($x, $y) { return $x / $y; };
$divideBy = F::flip($divide);

$divideBy(2, 10); // 5

对于柯里化的函数,此函数非常有用。它在组合链和点无表达式中非常有用。

id :: a -> a

返回它所得到的任何东西!再次,这在组合链中非常有用,当你不希望对值做任何事情时(参见converge

<?php

use PhpFp\Combinators as F;

F::id(2); // 2
F::id('hello'); // hello

ifElse :: (a -> Bool), (a -> b), (a -> b) -> a -> b

此函数允许在组合链中进行条件判断。与分支和合并的converge不同,ifElse根据谓词选择要运行的函数,另一个函数将被忽略

<?php

use PhpFp\Combinators as F;

$isOdd = function ($x) { return $x % 2 === 1; };
$odd = function ($x) { return $x * 3 + 1; };
$even = function ($x) { return $x / 2; };

$collatz = F::ifElse($isOdd, $odd, $even);
$collatz(3); // 10
$collatz(10); // 5

K :: a -> b -> a

此函数接受一个值,然后返回一个函数,该函数无论接收什么都会返回该值。这创建了一个“常量”函数来包装值,在需要调用的地方

<?php

use function PhpFp\Combinators;

$isOdd = function ($x) { return $x % 2 === 1; };

$f = F::ifElse($isOdd, K('Oops!'), function ($x) { return "$x is even!"; });
$f(1); // 'Oops!'
$f(2); // '2 is even!'

on :: (b, b -> c), (a -> b) -> a, a -> c

此函数也称为Psi组合子,允许您对值的变换调用函数。这对于诸如按对象的特定属性排序之类的事情非常有用:我们可以根据变换在两个对象上调用比较函数。最好用一个例子来说明

<?php

// Get an array value.
$prop = function ($k)
{
    return function ($xs) use ($k)
    {
        return $xs[$k];
    };
};

// Sort arrays by their 'test' key.
$sort = function ($xs, $f) use ($prop)
{
    $ys = array_slice($xs, 0);
    usort($ys, on($f, $prop('test')));

    return $ys;
};

// Standard comparison function.
$f = function ($a, $b) { return $a <=> $b; };

$test = [
    ['title' => 'hello',     'test' => 3],
    ['title' => 'goodbye',   'test' => 2],
    ['title' => 'something', 'test' => 4]
];

array_column($sort($test, $f), 'title'); // ['goodbye', 'hello', 'something']

贡献

如果我遗漏了您喜欢的任何组合器,请随时提交PR。如果您有任何使这些README更清晰的优秀想法,那将非常棒:尽管这些组合器对于函数式程序员来说并不陌生,但它们确实很复杂,需要很好地解释。所有帮助都备受感激:)