FWIW, I don't consider type safety a major issue with FP vs. OOP vs. procedural. I think type safety is just that, a safety net. I've ported things between C#, Scala, and PHP for fun, and regularly find PHP to be more concise due to it's lack of type safety than it being a hinderance. Sure, it sucks that the IDE can't help me out more (lack of generics
cough) but static analysis tools really help there, like Psalm and PHPStan. As a side note, Psalm's security scans have pointed out security issues with the original code it was ported from, so that's something...
You can do some pretty fancy things with arrays that you usually only see in FP type languages:
$arr1 + $arr2 (non-numeric keys) // scala: arr1 ++ arr2
array_merge($arr1, $arr2) // scala: (arr1 ++ arr2) distinct
array_unique(array_merge($arr1, $arr2)) // scala: arr1 union arr2
array_intersect($arr1, $arr2) // scala: arr1 intersect arr2
array_combine($arr1, $arr2) // scala: arr1 zip arr2
array_filter(array_map($mapper(...), $arr)) // scala: arr.flatmap(mapper)
in all of these cases, the original array(s) remains untouched. In most OOP languages, the array would probably be mutable (or require some juggling between mutable and immutable types, like C#). That's why its surprising. It's quite verbose in PHP, but the foundations for a FP approach is all there.
What's even more surprising is when performance is comparable to a language like C# on some random benchmarks I've run[1] (opcache + JIT turned on in PHP, C# in "release" optimized compilation). I'd consider it a pretty good contender for serious things.
[1]: https://github.com/withinboredom/distributed-hashmap/blob/23...