This is an 'ancient' idea pre-dating the recent functional craze: array programming, it is so well known that it has a substantial wikipedia page:<p><a href="http://en.wikipedia.org/wiki/Array_programming" rel="nofollow">http://en.wikipedia.org/wiki/Array_programming</a><p>its also important to note that this is syntactic sugar - and like most kinds of syntactic sugar it can make code confusing to read, in order to make it prettier. being explicit is often a very good thing for readability and for compilers (they must also read your code) - i value it highly.<p>although there is something nice about being able to add two arrays together and it do 'what i would expect'... but what do i expect if the arrays do not match in size? how much more thinking do i need to do over being explicit?
This is a standard feature of many languages or libraries, and generally known as <i>array programming</i> – something APL is known for. It crops up in numerical libraries like "numpy" (Python) or "PDL" (Perl) where selected scalar operations distribute over the whole collection. This is great when using collections of numbers, but is not very generalizable: It may not be possible to distinguish whether a method was called on a collection or all items in the collection. One solution would be a “mapping method call operator” like "!" (it's like a method call "." <i>and</i> a shell pipe "|") – but now we have an explicit "map" again.<p>I think an explicit "map" is more flexible in a general-purpose language. Some languages do interesting experiments with this, e.g. Perl6 which uses “hyperoperators” to precisely control how a given operator is applied.
How many times will Monads be reinvented?<p><pre><code> name.trim.filter{ _.length != 0 }.toUpperCase
</code></pre>
becomes:<p><pre><code> name >>= (return . trim) >>= (guard . ((/= 0) . length)) >>= (return . toUpperCase)
</code></pre>
I've purposefully used >>= and return instead of fmap to show that '.' above is almost >>=.<p>EDIT: I've just noticed a type error in the use of guard, but you get the idea.
The problem I see is that implicit mapping restricts the scope of operations that can work on collections -- if there is no distinction between applying an operation to an single object and applying the same operation to all members of a collection, then no collection can directly support the same operation as anything which might be a member of the collection, because you can't disambiguate between attempts to operate on the collection and attempts to operate on the members.<p>This would seem to be a problem in general, and a particular problem for nested collections. Explicitness makes intent clear.
The example in the article was taken directly from the Scala documentation for [Option](<a href="http://www.scala-lang.org/api/current/index.html#scala.Option" rel="nofollow">http://www.scala-lang.org/api/current/index.html#scala.Optio...</a>). The map <i>is</i> implicit if you use Scala's for notation. From the linked docs:<p><pre><code> val upper = for {
name <- request getParameter "name"
trimmed <- Some(name.trim)
upper <- Some(trimmed.toUpperCase) if trimmed.length != 0
} yield upper
println(upper getOrElse "")
</code></pre>
In Scala, an implementation of flatMap (bind), map, and filter allows you to use for expressions like the above. Objects that support these operations are not strictly monads, but they're close enough for most practical uses. Haskell is great, but give Scala a little credit.
This is somewhat similar to the List monad in Haskell:<p><a href="http://en.m.wikibooks.org/wiki/Haskell/Understanding_monads/List" rel="nofollow">http://en.m.wikibooks.org/wiki/Haskell/Understanding_monads/...</a><p>Bind is concatMap and return puts something into a singleton list. This allows "nondeterministic" computations, where applying functions over all elements in the list is implicit (via bind). Using the monad is not the same as having map be implicit everywhere, but it allows cases where you need several chained implicit (concat)maps to be cleanly implemented.<p>This is arguably a better design than making all functions polymorphic over lists, and having implicit maps be a global rule (rather than something constrained in a monad's context).
How difficult will code be to read if implicit operations are happening without any mention of the language construct executing them?
As far as this goes, Haskell's Maybe monad is the simplest system I've ever seen:<p><pre><code> let x = Just 3 in
do
value <- x
guard (value > 1)
return (value * 4)
</code></pre>
If x was 'Nothing' then the whole operation would short circuit and 'Nothing' would be returned. If the guard fails, then 'Nothing' is returned.
My favourite example of a language with 'automatic functorization' is Icon/Unicon. All functions, when applied to generators, themselves become generators.<p>So e.g. `read` is a generator that reads lines from the input, `write` writes a line to output, and the composition of them, `write(read())`, is a generator that copies lines from input to output. To run the generator, you can write `while write(read())`.
> What would our languages look like if we made them shape polymorphic? If we moved in that direction it would be like baking the Composite Design Pattern deeply into language machinery. It could be very powerful.<p>In addition to APL and J, that would look a lot like SQL as well.
Erik Meijer points to this as research in this area: <a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.146.5411" rel="nofollow">http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.146....</a>