-
Notifications
You must be signed in to change notification settings - Fork 698
[Question] How to express a recursive type? #2777
Copy link
Copy link
Closed
Description
Hello there!
I try to type a flatten() function from the nikic\iter package. I have no ideas how to do this using current psalm. I would appreciate any help. I have copied the function definition below:
source:
/**
* Takes an iterable containing any amount of nested iterables and returns
* a flat iterable with just the values.
*
* The $level argument allows to limit flattening to a certain number of levels.
*
* Examples:
*
* iter\flatten([1, [2, [3, 4]], [5]])
* => iter(1, 2, 3, 4, 5)
* iter\flatten([1, [2, [3, 4]], [5]], 1)
* => iter(1, 2, [3, 4], 5)
*
* @param iterable $iterable Iterable to flatten
* @param int $levels Number of levels to flatten
*
* @return \Iterator
*/
function flatten(iterable $iterable, $levels = INF): \Iterator {
if ($levels < 0) {
throw new \InvalidArgumentException(
'Number of levels must be non-negative'
);
}
if ($levels === 0) {
// Flatten zero levels == do nothing
yield from $iterable;
} else if ($levels === 1) {
// Optimized implementation for flattening one level
foreach ($iterable as $key => $value) {
if (isIterable($value)) {
yield from $value;
} else {
yield $key => $value;
}
}
} else {
// Otherwise flatten recursively
foreach ($iterable as $key => $value) {
if (isIterable($value)) {
yield from flatten($value, $levels - 1);
} else {
yield $key => $value;
}
}
}
}This is what I did so far:
First attempt:
/**
* FIXME: probably not solvable without recursive types like in TypeScript.
* Types are only describen for given nesting level of 1.
*
* @template T
*
* @param iterable<T|iterable<T>> $iterable
* @param int $levels
* @return \Iterator<T>
*/
function flatten(iterable $iterable, $levels = INF): \Iterator {}Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels