The Profunctor
models a generalization of functions. Its instances have two type variables, one which changes in a
covariant fashion, the other contravariantly.
The Profunctor
typeclass provides a single method which allows mapping on both type variables at the same time,
covariantly on one and contravariantly on the other.
interface Profunctor
{
/**
* @param callable(A): B $f
* @param callable(C): D $g
* @param F<B, C> $a
* @return F<A, D>
*/
public function diMap(callable $f, callable $g, $a);
}
Its simplified type signature is
(A -> B, C -> D, F<B, C>) -> F<A, D>
The ExtraProfunctor
class uses the Profunctor
instance to map separately on the covariant and on the contravariant
type variables.
final class ExtraProfunctor
{
/**
* @param callable(A): B $f
* @param F<C, A> $fca
* @return F<C, B>
*/
public function rmap(callable $f, $fca)
/**
* @param callable(A): B $f
* @param F<B, C> $fbc
* @return F<A, C>
*/
public function lmap(callable $f, $fbc)
}
Their simplified type is
rmap :: (A -> B, F<C, A>) -> F<C, B>
lmap :: (A -> B, F<B, C>) -> F<A, C>
The laws of the Profunctor
typeclass are the same of the Bifunctor
typeclass, with the slight twist given by the
contravariant type variable.
$profunctor->diMap(fn($x) => $x, fn($x) => $x, $a) == $a
$profunctor->diMap(fn($x) => $f($g($x)), fn($x) => $h($k($x)), $a) == $profunctor->diMap(fn($x) => $g($x), fn($x) => $h($x), $profunctor->diMap(fn($x) => $f($x), fn($x) => $k($x)), $a)