lstrojny / functional-php

Primitives for functional programming in PHP
MIT License
1.98k stars 204 forks source link

Support psalm #208

Open lstrojny opened 4 years ago

lstrojny commented 4 years ago

Add psalm annotations

Type specificity

Issues

alexeyshockov commented 4 years ago

Nice to see that you decided to go with Psalm! I think this is the best choice for a lib like yours, where templates and @psalm- specific annotations can really help end users.

I would like to help with the integration, if you don't mind (and if it's really needed...). Can start from the end of the list, to not mess with you.

alexeyshockov commented 4 years ago

@lstrojny, please take a look at #209

lstrojny commented 4 years ago

@alexeyshockov it would be terrific to collaborate on this topic. I've just pushed my current WIP, would you mind rebasing. Unfortunately it’s going to create a few conflicts, sorry about that. How about we agree to mark an item before working on it, so we avoid duplicate work?

jkuchar commented 4 years ago

@ondrejmirtes Could @phpstan 0.12 also benefit from this work to make this available to even broader user base?

ondrejmirtes commented 4 years ago

@jkuchar PHPStan can benefit from generics annotations, not from "pure" or "assert" yet. Instead of assert annotations, right now a TypeSpecifyingExtension has to be written. There are already extensions like that for PHPUnit, for beberlei/assert and webmozart/assert.

Of course, an extension like this can be written to interpret these phpDoc annotations but no one did that yet.

foalford commented 4 years ago

One little thing to add: comment of variable length argument need a fix

It should be mixed ...$arguments. Otherwise, psalm always reports an error.

InvalidArgument - src/test.php:151:56 - Argument 2 of Functional\partial_right expects array<array-key, mixed>, string(BASE) provided
klimick commented 4 years ago

Hi @lstrojny! Since 3.11.3 Psalm supports func_num_args() for conditional types. You could use for compose but with compromises.

/**
 * @template A
 * @template B
 * @template C
 * @template D
 * @template F
 * @template G
 * @template H
 * @template I
 *
 * @param callable(A):B $aToB
 * @param callable(B):C $bToC
 * @param callable(C):D $cToD
 * @param callable(D):F $dToF
 * @param callable(F):G $fToG
 * @param callable(G):H $gToH
 * @param callable(H):I $hToI
 *
 * @return (func_num_args() is 2 ? callable(A):C : (
 *          func_num_args() is 3 ? callable(A):D : (
 *          func_num_args() is 4 ? callable(A):F : (
 *          func_num_args() is 5 ? callable(A):G : (
 *          func_num_args() is 6 ? callable(A):H : (
 *          func_num_args() is 7 ? callable(A):I : callable
 *         ))))))
 */
function compose(
    callable $aToB,
    callable $bToC,
    callable $cToD = null,
    callable $dToF = null,
    callable $fToG = null,
    callable $gToH = null,
    callable $hToI = null,
    callable ...$others
) {
    // impl here
}

In this case you can type limited arguments count. After the limit compose will return just callable.

Unfortunately you can pass null value instead of one of callable.

A similar solution used by rxjs

Inference example: image

Error example: image

lstrojny commented 4 years ago

@klimick that’s a great idea, thank you!

jkuchar commented 3 years ago

Isn't this ready to be merged? (even incomplete) :-)

adrienbrault commented 2 years ago

Hey, for anyone interested in psalm/phpstan support, there is an alternative to this library that has generics: azjezz/psl.