|
> In my opinion, with few exceptions, the kind of programs advocates of dynamic typing want to write that static typing would have trouble dealing with, are artificial and not the common case. (Not "map" though, I need to review that case, but "map" is definitely a common and useful function!) I mostly agree, don't get me wrong. And it's important to note that Common Lisp's `map` functions do more than what people traditionally associate with `map` - they basically do `map(foo, zip(zip(list1, list2), list3)...)`. Still, this is a pretty useful property, and it is very natural and safe to use or implement, while being impossible to give a type to in most languages. C++ can do it with the template system, as can Rust with macros (so, using dynamic typing at compile time). Haskell can make it look pretty decent (if you can stand operator soup) by relying on auto-currying and inline operators and a few helper functions. I would also note that the Haskell creators also though that this functionality is useful, so they implemented some of the required boilerplate in the standard lib already. In most languages, you can implement it with lambdas and zips (or reflection, of course). So I think that this is a nice example of a function that is not invented out of thin air, is useful, is perfectly safe and static in principle, but nevertheless is impossible to write "directly" in most statically typed languages. Just to show the full comparison, here is how using this would look in CL, Haskell and C#: CL
(map 'list #'max3 '(1 3 5) '(-1 4 0) '(6 1 8))
Haskell
max3 <$> ZipList [1 3 5] <*> ZipList [-1,4,0] <*> ZipList [6,1,8]
OR
(<*>) ((<*>) ((<$>) max3 (ZipList [1,2])) (ZipList [-1,4])) (ZipList [3,1])
C#
new int[]{1,3,5}.Zip<int,int,Func<int,int>>(new int[]{-1,4,0}, (a,b) => (c) => max3(a, b, c)).Zip(new int[]{6, 1, 8}, (foo,c) => foo(c))
Note only the CL version, out of all these languages, can work for a function known at runtime instead of compile-time. None of the static type systems in common use can specify the type of this function, as they can't abstract over function arity.Here's a paper showing how this was handled in Typed Scheme: https://www2.ccs.neu.edu/racket/pubs/esop09-sthf.pdf |