Re: Constraints vs. values as types?
| From: | Ben Ramsey | Date: | Sun, 17 Apr 2022 20:48:02 +0000 |
| Subject: | Re: Constraints vs. values as types? | ||
| References: | 1 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-117539@lists.php.net to get a copy of this message | ||
> On Apr 16, 2022, at 23:48, Mike Schinkel <mike@newclarity.net> wrote:
>
> Hi PHPers,
>
> As I have been following the discussion about the need for a "true" type to allow
> documenting that a function should only be able to return true vs. bool which would allow false, and
> in the past the same argument for false vs. true, it occurs to me that there is another approach to
> address this rather than add values to be types which AFAIK has not been mentioned on the list
> before.
>
> An alternate solution to possibly consider might be to add the concept of
> "constraints" to PHP that could work alongside types. This occured to me because I am
> mostly doing Go programming now and constraints is effectively how Go handled an equivalent
> conundrum for the Generics they just added.
>
> Consider if PHP allowed the following and if PHP would allow type hints to use *either* a type
> *or* a constraint where the values on the right hand side are expressions (I was just spitballing
> the syntax; other syntaxes or even concept names might represent this concept better):
>
> constraint true: true
>
> constraint false: false
>
> If we had constraints in PHP we could also have things like this:
>
> constraint Truthy: !empty($this)
>
> constraint Falsey: empty($this)
>
> constraint Percent: is_numeric($this) && 0 <= $this && $this <=100
>
> constraint DateTimeable: is_object($this)
> && (get_class=($this) == DateTime::class || get_class=($this) ==
> DateTimeImmutable::class)
>
> constraint ProductID: is_string($this) && strlen($this)==10
> && preg_match("#[A-Z]{2}[0-9]{8}#",$this)
>
> With the above, we could write functions like this and know they are more "type safe"
> than otherwise:
>
> function product_exists(ProductID $product_id):bool {...}
>
> Constraints could also be limited to using only standard library functions so that it would be
> possible to do static analysis on a constraint. Clearly a static analyzer could evaluate the
> constraints I represented above. And I *think* this could be backward compatible with false as a
> type, and even true with a type.
>
> FWIW I am just offering up an approach that seems to have worked well in Go for consideration.
> If you like it, please discuss it. If not, it was worth a try.
>
> -Mike
>
> P.S. I am sure there are many ways to improve what I proposed. Note this is *just* a straw man
> proposal; please offer suggestions for improvement.
>
This reminds me of some of the discussion we’ve had on list of type aliasing.[^1]
I really like this idea and think it could be combined with type aliasing to create powerful
userland-defined types.
While you mention restricting to standard-library functions for easier type-safety, I’m not sure
it has to have that limitation. What we’re effectively defining here is a kind of short-hand
Closure that is then called with the passed value at runtime to validate the type. A type alias
could work similarly, perhaps even with the same syntax.
Cheers,
Ben
[^1]: https://externals.io/message/112209#112214