{
return $value instanceof Foldable
? $value
- : Listt::of(toNativeTraversable($value));
+ : fromIterable($value);
}
/**
{
return $value instanceof Traversable
? $value
- : Listt::of(toNativeTraversable($value));
+ : fromIterable($value);
}
-/**
- * @var callable
- */
-const concat = 'Widmogrod\Functional\concat';
-
-/**
- * concat :: Foldable t => t [a] -> [a]
- *
- * <code>
- * concat([[1, 2], [3, 4]]) == [1, 2, 3, 4]
- * </code>
- *
- * The concatenation of all the elements of a container of lists.
- *
- * @param Foldable $foldable
- *
- * @return array
- */
-function concat(Foldable $foldable)
-{
- return reduce(function ($agg, $value) {
- return reduce(function ($agg, $v) {
- $agg[] = $v;
-
- return $agg;
- }, $agg, toFoldable($value));
- }, [], $foldable);
-}
-
-/**
- * @var callable
- */
-const toList = 'Widmogrod\Functional\toList';
-
-/**
- * toList :: Traversable t -> t a -> [a]
- *
- * @param Foldable $traversable
- *
- * @return mixed
- */
-function toList(Foldable $traversable)
-{
- return reduce(push_, [], $traversable);
-}
/**
* Curry function
$argsLeft = $numberOfArguments - func_num_args();
return $argsLeft <= 0
- ? call_user_func_array($function, push_($args, $argsNext))
+ ? $function(...push_($args, $argsNext))
: curryN($argsLeft, $function, push_($args, $argsNext));
};
}
return reduce(
flip($callable),
$accumulator,
- reduce(function ($accumulator, $value) {
- return concatM(Listt::of([$value]), $accumulator);
- }, Listt::of([]), $foldable)
+ reduce(flip(prepend), Listt::mempty(), $foldable)
);
})(...func_get_args());
}
* Map each element of a structure to an action, evaluate these actions from left to right, and collect the results
*
* @param callable $transformation (a -> f b)
- * @param Traversable $t t a
+ * @param Traversable $t t a
*
* @return Applicative f (t b)
*/
/**
* filterM :: Monad m => (a -> m Bool) -> [a] -> m [a]
*
- * @param callable $f (a -> m Bool)
+ * @param callable $f (a -> m Bool)
* @param array|Traversable $collection [a]
*
* @return Monad m [a]
/**
* foldM :: Monad m => (a -> b -> m a) -> a -> [b] -> m a
*
- * @param callable $f (a -> b -> m a)
- * @param mixed $initial a
+ * @param callable $f (a -> b -> m a)
+ * @param mixed $initial a
* @param array|\Traversable $collection [b]
*
* @return mixed m a
namespace Widmogrod\Functional;
+use Widmogrod\FantasyLand\Foldable;
use Widmogrod\Primitive\Listt;
function fromIterable(iterable $i): Listt
return Listt::of(array_map(identity, $i));
}
-///**
-// * concat :: Foldable t => t [a] -> [a]
-// *
-// * The concatenation of all the elements of a container of lists.
-// */
-//function concat(Foldable $t)
-//{
-// // TODO
-//}
+/**
+ * @var callable
+ */
+const concat = 'Widmogrod\Functional\concat';
+
+/**
+ * concat :: Foldable t => t [a] -> [a]
+ *
+ * <code>
+ * concat(fromIterable([fromIterable([1, 2]), fromIterable([3, 4])])) == fromIterable([1, 2, 3, 4])
+ * </code>
+ *
+ * concat :: Foldable t => t [a] -> [a]
+ * concat xs = build (\c n -> foldr (\x y -> foldr c y x) n xs)
+ *
+ * build :: forall a. (forall b. (a -> b -> b) -> b -> b) -> [a]
+ * build g = g (:) []
+ *
+ * foldr :: (a -> b -> b) -> b -> [a] -> b
+ *
+ * The concatenation of all the elements of a container of lists.
+ *
+ * @param Foldable $xs
+ *
+ * @return Listt
+ */
+function concat(Foldable $xs)
+{
+ return foldr(function ($x, Listt $y) {
+ return foldr(prepend, $y, $x);
+ }, Listt::mempty(), $xs);
+}
///**
// * map f xs is the list obtained by applying f to each element of xs, i.e.,
*/
function prepend($x, Listt $xs = null)
{
- return curryN(2, function ($x, Listt $xs) {
+ return curryN(2, function ($x, Listt $xs): Listt {
return append(fromIterable([$x]), $xs);
})(...func_get_args());
}
* [x1, ..., xm] ++ [y1, ...] == [x1, ..., xm, y1, ...]
*
* If the first list is not finite, the result is the first list.
+ *
+ * @param Listt $a
+ * @param Listt|null $b
+ * @return Listt|callable
*/
-function append(Listt $a, Listt $b): Listt
+function append(Listt $a, Listt $b = null)
{
- return $a->concat($b);
+ return curryN(2, function (Listt $a, Listt $b): Listt {
+ return $a->concat($b);
+ })(...func_get_args());
}
///**
*/
public function __construct($value)
{
- $this->value = f\isNativeTraversable($value)
- ? $value
- : [$value];
+ $givenType = is_object($value) ? get_class($value) : gettype($value);
+ assert(is_iterable($value), "Not iterable value given $givenType");
+
+ $this->value = $value;
}
/**
public function bind(callable $transformation)
{
// xs >>= f = concat (map f xs)
- return self::of(f\concat(f\map($transformation, $this)));
+ return f\concat(f\map($transformation, $this));
}
/**
$accumulator[] = $item;
return $accumulator;
- }, $this->extract()));
+ }, $this->value));
}
throw new TypeMismatchError($value, self::class);
public function provideData()
{
return [
- 'list' => [
- '$array' => f\toFoldable(['foo', 1]),
- '$expected' => ['foo', 1],
- ],
'list of lists' => [
- '$array' => f\toFoldable([['a', 1], ['b', 2]]),
- '$expected' => ['a', 1, 'b', 2],
+ '$array' => f\fromIterable([
+ f\fromIterable(['a', 1, 3]),
+ f\fromIterable(['b', 2, 4])
+ ]),
+ '$expected' => f\fromIterable(['a', 1, 3, 'b', 2, 4]),
],
'list of lists of lists' => [
- '$array' => f\toFoldable([
- [
- ['a', 1],
- ['b', 2]
- ],
- [
- ['c', 3]
- ],
+ '$array' => f\fromIterable([
+ f\fromIterable([
+ f\fromIterable(['a', 1]),
+ f\fromIterable(['b', 2])
+ ]),
+ f\fromIterable([
+ f\fromIterable(['c', 3])
+ ]),
+ ]),
+ '$expected' => f\fromIterable([
+ f\fromIterable(['a', 1]),
+ f\fromIterable(['b', 2]),
+ f\fromIterable(['c', 3])
]),
- '$expected' => [['a', 1], ['b', 2], ['c', 3]],
],
'list of lists of lists with some noregulatives' => [
- '$array' => f\toFoldable([
- [
- ['a', 1],
- ['b', 2]
- ],
- ['c', 3]
+ '$array' => f\fromIterable([
+ f\fromIterable([
+ f\fromIterable(['a', 1]),
+ f\fromIterable(['b', 2]),
+ ]),
+ f\fromIterable(['c', 3])
+ ]),
+ '$expected' => f\fromIterable([
+ f\fromIterable(['a', 1]),
+ f\fromIterable(['b', 2]),
+ 'c',
+ 3
]),
- '$expected' => [['a', 1], ['b', 2], 'c', 3],
],
];
}