Skip to content

Commit

Permalink
Functional\repeat test + implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
widmogrod committed Dec 21, 2017
1 parent 0c43a64 commit 5703221
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 47 deletions.
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"src/Functional/listt.php",
"src/Functional/zipping.php",
"src/Functional/sublist.php",
"src/Functional/infinit.php",
"src/Functional/predicates.php",
"src/Functional/strings.php",
"src/Functional/monoid.php",
Expand Down
117 changes: 117 additions & 0 deletions src/Functional/infinit.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<?php

namespace Widmogrod\Functional;

use Widmogrod\Primitive\EmptyListError;
use Widmogrod\Primitive\Listt;
use Widmogrod\Primitive\ListtCons;
use Widmogrod\Primitive\ListtNil;
use function Widmogrod\Useful\match;

/**
* @var callable
*/
const iterate = 'Widmogrod\Functional\iterate';

/**
* iterate :: (a -> a) -> a -> [a]
*
* iterate f x returns an infinite list of repeated applications of f to x:
*
* ```haskell
* iterate f x == [x, f x, f (f x), ...]
* ```
* @param callable $fn
* @param mixed $a
* @return Listt
*/
function iterate(callable $fn, $a = null)
{
return curryN(2, function (callable $fn, $a): Listt {
return ListtCons::of(function () use ($fn, $a) {
return [$a, iterate($fn, $fn($a))];
});
})(...func_get_args());
}

/**
* @var callable
*/
const repeat = 'Widmogrod\Functional\repeat';

/**
* repeat :: a -> [a]
*
* repeat x is an infinite list, with x the value of every element.
*
* @param $a
* @return mixed|ListtCons
*/
function repeat($a)
{
return ListtCons::of(function () use ($a, &$list) {
return [$a, repeat($a)];
});
}

/**
* @var callable
*/
const replicate = 'Widmogrod\Functional\replicate';

/**
* replicate :: Int -> a -> [a]
*
* replicate n x is a list of length n with x the value of every element.
* It is an instance of the more general genericReplicate, in which n may be of any integral type.
*
* @param int $n
* @param mixed $a
* @return Listt
*/
function replicate(int $n, $a = null): Listt
{
return curryN(2, function (int $n, $a): Listt {
if ($n < 1) {
return fromNil();
}

return ListtCons::of(function () use ($n, $a) {
return [$a, replicate($n - 1, $a)];
});
})(...func_get_args());
}

/**
* @var callable
*/
const cycle = 'Widmogrod\Functional\cycle';

/**
* cycle :: [a] -> [a]
*
* cycle ties a finite list into a circular one, or equivalently, the infinite repetition of the original list. It is the identity on infinite lists.
*
* @param Listt $l
* @return Listt
* @throws EmptyListError
*/
function cycle(Listt $l): Listt
{
if ($l instanceof ListtNil) {
throw new EmptyListError(__FUNCTION__);
}

$cycle = match([
ListtNil::class => function () use (&$next) {
return $next;
},
ListtCons::class => identity
]);

$next = ListtCons::of(function () use ($l, $cycle) {
return [head($l), $cycle(tail($l))];
});

return $next;
}
47 changes: 0 additions & 47 deletions src/Functional/list_infinit.php

This file was deleted.

26 changes: 26 additions & 0 deletions test/Functional/RepeatTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

namespace test\Functional;

use Widmogrod\Primitive\Listt;
use function Widmogrod\Functional\head;
use function Widmogrod\Functional\repeat;
use function Widmogrod\Functional\tail;

class RepeatTest extends \PHPUnit_Framework_TestCase
{
public function test_it($value = 'ab')
{
$result = repeat($value);
$this->assertInstanceOf(Listt::class, $result);

$this->assertSame($value, head($result));
$this->assertSame($value, head(tail($result)));

$it = $result->getIterator();
$this->assertInstanceOf(\Generator::class, $it);
$this->assertSame($value, $it->current());
$it->next();
$this->assertSame($value, $it->current());
}
}

0 comments on commit 5703221

Please sign in to comment.