2017 © Pedro Peláez
 

library phunkie

Functional structures library for PHP

image

phunkie/phunkie

Functional structures library for PHP

  • Tuesday, January 9, 2018
  • by md
  • Repository
  • 15 Watchers
  • 191 Stars
  • 1,783 Installations
  • PHP
  • 3 Dependents
  • 0 Suggesters
  • 13 Forks
  • 0 Open issues
  • 14 Versions
  • 26 % Grown

The README.md

Phunkie

Build Status, (*1)

Phunkie is a library with functional structures for PHP., (*2)

Full documentation is available here., (*3)

For better Phunkie development, consider installing phunkie-console., (*4)

$ bin/phunkie-console
Welcome to phunkie console.

Type in expressions to have them evaluated.

phunkie >

Options

phunkie > Some(1)
$var0: Option<Int> = Some(1)

phunkie > None()
$var1: None = None

phunkie > Option(42)
$var2: Option<Int> = Some(42)

phunkie > Option(null)
$var3: None = None

Immutable Lists

You can import phunkie modules with the :import command. Use :help for more information, (*5)

phunkie > ImmList(2,3,4)
$var0: List<Int> = List(2, 3, 4)

phunkie > ImmList(Some(1), None(), Some(3))
$var1: List<Int> = List(Some(1), None, Some(3))

phunkie > :import immlist/*
imported function \Phunkie\Functions\immlist\head()
imported function \Phunkie\Functions\immlist\init()
imported function \Phunkie\Functions\immlist\tail()
imported function \Phunkie\Functions\immlist\last()
imported function \Phunkie\Functions\immlist\reverse()
imported function \Phunkie\Functions\immlist\length()
imported function \Phunkie\Functions\immlist\concat()
imported function \Phunkie\Functions\immlist\take()
imported function \Phunkie\Functions\immlist\drop()
imported function \Phunkie\Functions\immlist\nth()
imported function \Phunkie\Functions\immlist\filter()
imported function \Phunkie\Functions\immlist\reject()
imported function \Phunkie\Functions\immlist\reduce()

phunkie > head (ImmList(1,2,3))
$var2: Int = 1

phunkie > tail (ImmList(1,2,3))
$var3: List<Int> = List(2, 3)

phunkie > init (ImmList(1,2,3))
$var4: List<Int> = List(1, 2)

phunkie > last (ImmList(1,2,3))
$var5: Int = 3

phunkie > reverse (ImmList(1,2,3))
$var6: List<Int> = List(3, 2, 1)

phunkie > length (ImmList(1,2,3))
$var7: Int = 3

phunkie > ImmList("Black", "Red", "Green")->filter(function($x) { return $x != "Green"; })
$var8: List<String> = List("Black", "Red")

phunkie > ImmList("Black", "Red", "Green")->partition(function($x) { return $x != "Green"; })
$var9: (List<String>, List<String>) = Pair(List("Black", "Red"), List("Green"))

phunkie > ImmList("A","B","C")->zip(ImmList(1,2,3))
$var10: List<(String, Int)> = List(Pair("A", 1), Pair("B", 2), Pair("C", 3))

Immutable Sets and Immutable Maps

phunkie > ImmSet(1,2,3)
$var0: Set<Int> = Set(1, 2, 3)

phunkie > ImmSet(1,2,3,2) // No duplicates
$var1: Set<Int> = Set(1, 2, 3)

phunkie > ImmSet(1,2,3)->contains(3)
$var2: Boolean = true

phunkie > ImmSet(1,2,3)->minus(3) // creates a new set
$var3: Set<Int> = Set(1, 2)

phunkie > ImmSet(1,2,3)->plus(4) // again, new set
$var4: Set<Int> = Set(1, 2, 3, 4)

phunkie > ImmMap(["hello" => "there"])
$var5: Map<String, String> = Map("hello" -> "there")

phunkie > ImmMap(["hello" => "there"])->get("hello")
$var6: Option<String> = Some("there")

phunkie > ImmMap(["hello" => "there"])->get("zoom")
$var7: None = None

phunkie > ImmMap(["hello" => "there"])->plus("hi", "here") // creates a new Map
$var8: Map<String, String> = Map("hello" -> "there", "hi" -> "here")

phunkie > class Id {
phunkie {     private $number;
phunkie {     public function __construct($n)
phunkie {     {
phunkie {         $this->number = $n;
phunkie {     }
phunkie { }
defined class Id

phunkie > ImmMap(
phunkie (   new Id(1), "John Smith",
phunkie (   new Id(2), "Chuck Norris",
phunkie (   new Id(3), "Jack Bauer"
phunkie ( )
$var9: Map<Id, String> = Map(Id@2d05ca0 -> "John Smith", Id@2d05ca1 -> "Chuck Norris", Id@2d05ca2 -> "Jack Bauer")

Function1

phunkie > $f = Function1('strlen')
$f : Function1 = Function1(?=>?)

phunkie > $f("hello");
$var0: Int = 5

phunkie > $g = Function1(function($x) { return $x % 2 === 0; })
$g : Function1 = Function1(?=>?)

phunkie > $g($f("hello"))
$var1: Boolean = false

phunkie > $h = $g->compose($f)
$h : Function1 = Function1(?=>?)

phunkie > $h("hello")
$var2: Boolean = false

phunkie > $h = $f->andThen($g)
$h : Function1 = Function1(?=>?)

phunkie > $h("hello")
$var3: Boolean = false

Functor

phunkie > Some(1)->map(function($x) { return $x + 1;})
$var0: Option<Int> = Some(2)

phunkie > None()->map(function($x) { return $x + 1;})
$var1: None = None

phunkie > ImmList(1,2,3)->map(function($x) { return $x + 1;})
$var2: List<Int> = List(2, 3, 4)

phunkie > ImmList(1,2,3)->zipWith(function($x) { return $x + 1;})
$var3: List<(Int, Int)> = List(Pair(1, 2), Pair(2, 3), Pair(3, 4))

phunkie> :import functor/*
Imported function \Phunkie\Functions\functor\fmap()

phunkie > fmap (function($x) { return $x + 1;}, Some(42))
$var4: Option<Int> = Some(43)

Foldable

phunkie > ImmList(1,2,3)->foldLeft(0)(function($x, $y) { return $x + $y; })
$var0: Int = 6

phunkie > ImmList("a", "b", "c")->foldLeft("letters:")(function($x, $y) { return $x . $y; })
$var1: String = "letters:abc"

phunkie > ImmList("a", "b", "c")->foldRight("<--")(function($x, $y) { return $x . $y; })
$var2: String = "abc<--"

Currying

phunkie > $curried = ImmList(1,2,3)->foldLeft(0)(_)
$curried : Callable = <function>

phunkie > $curried(function($x, $y) { return $x + $y; })
$var0: Int = 6

phunkie > $implode = curry('implode')
$implode: Callable = <function>

phunkie > $implodeColon = $implode(":")
$implodeColon: Callable = <function>

phunkie > $implodeColon(["a", "b", "c"])
$var1: String = "a:b:c"

phunkie> :import immlist/take
Imported function \Phunkie\Functions\immlist\take

phunkie > $take = uncurry(take)
$take: Callable = <function>

phunkie > $take(2, ImmList(1,2,3))
$var2: List<Int> = List(1, 2)

Functor Composite

phunkie > $fa = Functor(Option)
$fa : Phunkie\Cats\Functor\FunctorComposite = Functor(Option)

phunkie > $fa->map(Option(1), function($x) { return $x + 1; })
$var0: Option<Int> = Some(2)

phunkie > fa->map(Option(ImmList(1,2,3)), function($x) { return $x + 1; })
Notice: Object of class Phunkie\Types\ImmList could not be converted to int

phunkie > $fa = Functor(Option)->compose(ImmList)
$fa : Phunkie\Cats\Functor\FunctorComposite = Functor(Option(List))

phunkie > $fa->map(Option(ImmList(1,2,3)), function($x) { return $x + 1; })
$var1: Option<List<Int>> = Some(List(2, 3, 4))

Applicative

phunkie > None()->pure(42)
$var0: Option<Int> = Some(42)

phunkie > ImmList()->pure(42)
$var1: List<Int> = List(42)

phunkie > Some(1)->apply(Some(function($x) { return $x + 1;}))
$var2: Option<Int> = Some(2)

phunkie > None()->apply(Some(function($x) { return $x + 1;}))
$var3: None = None

phunkie > ImmList(1,2,3)->apply(ImmList(function($x) { return $x + 1;}))
$var4: List<Int> = List(2, 3, 4)

phunkie > ImmList()->apply(ImmList(function($x) { return $x + 1;}))
$var5: List<Nothing> = List()

phunkie > Some(1)->map2(Some(2), function($x, $y) { return $x + $y; })
$var6: Option<Int> = Some(3)

phunkie > ImmList(1,2,3)->map2(ImmList(4,5,6), function($x, $y) { return $x + $y; })
$var7: List<Int> = List(5, 6, 7, 6, 7, 8, 7, 8, 9)

Monad

phunkie > ImmList(1,2,3)->flatMap(function($x) { return Some($x + 1); })
$var0: List<Int> = List(2, 3, 4)

phunkie > ImmList(1,2,3)->flatMap(function($x) { return $x % 2 === 0 ? None() : Some($x + 1); })
$var1: List<Int> = List(2, 4)

phunkie > ImmList(1,2,3)->flatMap(function($x) { return None(); })
$var2: List<Nothing> = List()

phunkie > ImmList(1,2,3)->flatMap(function($x) { return ImmList($x + 1, $x + 2); })
$var3: List<Int> = List(2, 3, 3, 4, 4, 5)

phunkie > Some(1)->flatMap(function($x) { return Some($x + 1); })
$var4: Option<Int> = Some(2)

phunkie > Some(1)->flatMap(function($x) { return None(); })
$var5: None = None

phunkie > None()->flatMap(function($x) { return Some(42); })
$var6: None = None

phunkie > ImmList(1,2,3)->flatMap(function($x) { return ImmList(Some($x + 1)); })
$var7: List<Option<Int>> = List(Some(2),Some(3),Some(4))

phunkie > Some(Some(42))->flatten()
$var8: Option<Int> = Some(42)

phunkie > ImmList(ImmList(1,2,3))->flatten()
$var9: List<Int> = List(1, 2, 3)

Kleisli

phunkie > $f = kleisli(function($x) { return Some($x + 1); })
$f: Phunkie\Cats\Kleisli = Phunkie\Cats\Kleisli@7b902640

phunkie > $g = kleisli(function($x) { return Some($x + 4); })
$g: Phunkie\Cats\Kleisli = Phunkie\Cats\Kleisli@7b902629

phunkie > $x = $f->andThen($g)
$x: Phunkie\Cats\Kleisli = Phunkie\Cats\Kleisli@7b902792

phunkie > $x->run(3)
$var0: Option<Int> = Some(8)

Monoid

phunkie > :import semigroup/*
Imported function \Phunkie\Functions\semigroup\combine()
Imported function \Phunkie\Functions\semigroup\zero()

phunkie > combine(1,1)
$var0: Int = 2

phunkie > combine("a","b")
$var1: String = "ab"

phunkie > combine([1,2,3], [4,5,6])
$var2: Array<Int> = [1, 2, 3, 4, 5, 6]

phunkie > combine(true, false)
$var3: Boolean = false

phunkie > combine(ImmList(1,2,3), ImmList(4,5,6))
$var4: List<Int> = List(1, 2, 3, 4, 5, 6)

phunkie > combine(Some(4), Some(2))
$var5: Option<Int> = Some(6)

phunkie > combine(Some("4"), Some("2"))
$var6: Option<String> = Some("42")

phunkie > ImmList(1,2,3)->combine(ImmList(4,5,6)
$var7: List<Int> = List(1, 2, 3, 4, 5, 6)

phunkie > zero(Option(42))
$var8: None = None

phunkie > Option(42)->zero()
$var9: None = None

phunkie > ImmList(1,2,3)->zero()
$var10: List<Nothing> = List()

phunkie > zero(rand(1,45))
$var11: Int = 0

phunkie > zero([1,2,3])
$var12: Array<Nothing> = []

Pattern Matching

Working withLists

<?php
use Phunkie\Types\ImmList;
use function Phunkie\PatternMatching\Referenced\ListWithTail;
use function Phunkie\PatternMatching\Referenced\ListNoTail;

function sum(ImmList $list): int { $on = pmatch($list); switch(true) {
    case $on(Nil): return 0;
    case $on(ListNoTail($x, Nil)): return $x;
    case $on(ListWithTail($x, $xs)): return $x + sum($xs);}
}

Validation monads wildcards

<?php

$boom = function () { return Failure(Nel(new \Exception("Boom!"))); };
$on = pmatch($boom()); switch (true) {
    case $on(Success(_)): return 2; break;
    case $on(Failure(_)): return 10; break;
}

$yay = function () { return Success("yay!"); };
$on = pmatch($yay()); switch (true) {
    case $on(Failure(_)): return 2; break;
    case $on(Success(_)): return 10; break;
}

Option wildcards

<?php

$on = pmatch(None()); switch (true) {
    case $on(None): return 10; break;
    case $on(Some(_)): return 2; break;
}

Lenses

phunkie > :import lens/*
imported function \Phunkie\Functions\lens\trivial()
imported function \Phunkie\Functions\lens\self()
imported function \Phunkie\Functions\lens\fst()
imported function \Phunkie\Functions\lens\snd()
imported function \Phunkie\Functions\lens\contains()
imported function \Phunkie\Functions\lens\member()
imported function \Phunkie\Functions\lens\makelenses()

phunkie > trivial()->get(42) // returns Unit which does not print anything

phunkie > trivial()->set(42,34)
$var0: Int = 34

phunkie > self()->get(42)
$var1: Int = 42

phunkie > self()->set(42,34)
$var2: Int = 42

phunkie > fst()->get(Pair(1,2))
$var3: Int = 1

phunkie > fst()->set(3, Pair(1,2))
$var4: (Int, Int) = Pair(3, 2)

phunkie > snd()->get(Pair(1,2))
$var5: Int = 2

phunkie > snd()->set(3, Pair(1,2))
$var6: (Int, Int) = Pair(1, 3)

phunkie > $s = ImmSet(1,2,3)
$s : ImmSet<Int> = Set(1, 2, 3)

phunkie > contains(2)->get($s)
$var7: Boolean = true

phunkie > contains(4)->set($s, true)
$var8: ImmSet<Int> = Set(1, 2, 3, 4)

phunkie > contains(3)->set($s, false)
$var9: ImmSet<Int> = Set(1, 2)

phunkie > $m = ImmMap(["a" => 1, "b" => 2])
$m : ImmMap<String, Int> = Map("a" -> 1, "b" -> 2)

phunkie > member("b")->get($m)
$var10: Option<Int> = Some(2)

phunkie > member("b")->set($m, None())
$var11: ImmMap<String, Int> = Map("a" -> 1)

phunkie > member("b")->set($m, Some(3))
$var12: ImmMap<String, Int> = Map("a" -> 1, "b" -> 3)

For comprehension

<?php

function letter($x)
{
    return Option($x);
}

function uppercase($x)
{
    return Option(strtoupper($x));
}

function quote($x)
{
    return Option('"' . $x . '"');
}

for_                            (__
    ($l  ) ->_ (letter('x'))    ,__
    ($u  ) ->_ (uppercase($l))  ,__
    ($res) ->_ (quote($u))      )
-> yields ($res);

// The above is the equivalent of:

$res = letter('x')->flatMap(function($l) {
    return uppercase($l)->flatMap(function($u) {
        return quote($u)->map(function($res) {
            return $res;
        });
    });
});

If the right hand side returns a tuple, it can be assigned to 2 separate variables, (*6)

<?php

$x = for_ (__
  ($left, $right) ->_ (Some(Pair("left", "right")))
) -> yields ($right);

// $x == "right"

You can $_ for ignored returned values:, (*7)

<?php

$x = for_ (__
  ($_, $right) ->_ (Some(Pair("left", "right")))
) -> yields ($right);

// $x == "right"

The Versions

09/01 2018

dev-master

9999999-dev

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

09/01 2018

0.10.2

0.10.2.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

16/07 2017

0.10.1

0.10.1.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

11/07 2017

0.10.0

0.10.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

09/06 2017

0.9.0

0.9.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

04/06 2017

0.8.1

0.8.1.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

03/06 2017

0.8.0

0.8.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

06/05 2017

0.7.0

0.7.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

15/04 2017

0.6.0

0.6.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

15/04 2017

0.5.0

0.5.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

15/04 2017

0.4.0

0.4.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

07/04 2017

0.3.0

0.3.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

25/03 2017

0.2.0

0.2.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires

23/03 2017

0.1.0

0.1.0.0

Functional structures library for PHP

  Sources   Download

MIT

The Requires

  • php >=7.0

 

The Development Requires