Kinds are type constructors that describe the “shape” of types in functional programming. They help us understand how types can be combined and manipulated.
The simplest kind, representing concrete types that have values. Examples:
Int
String
Boolean
Takes one type parameter to create a concrete type. Examples:
Option<A>
ImmList<A>
Set<A>
Takes two type parameters to create a concrete type. Examples:
Either<A, B>
Map<K, V>
Pair<A, B>
In Phunkie, kinds are represented through the Kind
interface:
use Phunkie\Types\Kind;
class Option implements Kind {
public const kind = "Option";
// ...
}
class ImmList implements Kind {
public const kind = ImmList;
// ...
}
Kinds are fundamental to type classes in Phunkie. Type classes like Functor
, Applicative
, and Monad
operate on types of kind * -> *
:
// Option is a Functor (kind -> )
$option = Option(42);
$doubled = $option->map(fn($x) => $x 2); // Some(84)
// ImmList is a Functor (kind -> )
$list = ImmList(1, 2, 3);
$doubled = $list->map(fn($x) => $x 2); // ImmList(2, 4, 6)
Higher-kinded types are type constructors that take other type constructors as parameters. While PHP doesn’t directly support higher-kinded types, Phunkie simulates them through its type class hierarchy:
/ Functor operations on different kinds
$option->map(fn($x) => $x + 1); // Option<A> -> Option<B>
$list->map(fn($x) => $x + 1); // ImmList<A> -> ImmList<B>
Option<A>
: Kind * -> *
ImmList<A>
: Kind * -> *
Map<K, V>
: Kind * -> * -> *
Function1<A, B>
: Kind * -> * -> *
To start the console, simply run:
$ bin/phunkie-console
Welcome to phunkie console.
Type in expressions to have them evaluated.
phunkie >
Then you can use the :type
command to show the type of an expression:
phunkie > :type Some(42)
Option<Int>
And the :kind
command to show the kind of a type:
phunkie > :kind Some(42)
* -> *
Type Safety: Kinds help ensure type-safe operations across different data structures
Abstraction: Allow writing generic code that works with any type of the appropriate kind
Composition: Enable composition of types and type classes in a predictable way
Documentation: Provide clear information about how types can be combined
Understanding kinds is essential for working with Phunkie’s type system and utilizing its functional programming features effectively.
Parametricity is a fundamental principle in functional programming that describes how polymorphic functions must behave uniformly across all types. In Phunkie, this means that the behavior of generic functions must be consistent regardless of the specific types they operate on.
// ImmList example - map behavior is consistent across types
$intList = ImmList(1, 2, 3);
$stringList = ImmList("a", "b", "c");
$intList->map(fn($x) => $x 2); // Behavior is consistent
$stringList->map(fn($x) => $x . $x); // Same structure, different type
// Option example - flatMap works the same way for any type
$intOption = Option(42);
$stringOption = Option("hello");
$intOption->flatMap(fn($x) => Option($x + 1)); // Some(43)
$stringOption->flatMap(fn($x) => Option($x . "!")); // Some("hello!")
map
, flatMap
, filter
work consistently$list->map(f)->map(g)
equals $list->map(fn($x) => g(f($x)))
// This works for any type A
function double<A>(ImmList<A> $list, callable $f): ImmList<A> {
return $list->map($f);
}
// Works with any Functor (Option, ImmList, etc.)
function increment($functor) {
return $functor->map(fn($x) => $x + 1);
}
While Phunkie implements parametricity principles, PHP’s type system has some limitations:
Despite these limitations, following parametricity principles in Phunkie helps write:
// Good - works with any type
function length/*<A>*/(ImmList/*<A>*/ $list): int {
return $list->length;
}
// Avoid - tied to specific type
function sumInts(ImmList/*<int>*/ $list): int {
return $list->reduce(fn($a, $b) => $a + $b);
}
// Works with any Monad
function chain/*<M>*/($monad, callable $f) {
return $monad->flatMap($f);
}
// Functor law: preserve identity
$list->map(fn($x) => $x) === $list
Understanding and applying parametricity in Phunkie leads to more robust and maintainable functional code, even within PHP’s type system limitations.