I'm sure the author is right about IO, but these sorts of articles always include such trivial examples that they do the opposite of the intended job. The one code snippet is from a dictionary look-up function. Here it is in Haskell:<p><pre><code> boo :: Map Integer String -> String -> Integer
</code></pre>
And here it is in C++ as a standalone function:<p><pre><code> template <class Key, class Value> Key boo (const Map<Key, Value> &, const Value &);
</code></pre>
or, more idiomatically, as part of a class:<p><pre><code> template <class Key, class Value> class Map {
[…]
Key boo(Value &val);
};
</code></pre>
The author's point is that the Haskell code can't do much other than use its parameters, because there is no IO involved, whereas the C++ version could do anything. Well, sure, it <i>could</i>, but let's be reasonable (which is all we can be without reading the code): it's probably gonna map a string to an int. It's just as likely that the Haskell code could do weird stuff (how does it behave if it finds multiple candidates for Value?) as the C++ code, practically speaking.<p>So this argument actually turns out to be an argument for good containers, or, more generally, for good built-in types. The author could make all those assumptions about his function from the type signature because he/she knew what "Map" meant, not because of anything inherent in Haskell's type system. I mean, I grant that Haskell has a great type system, and great built-in types. It's just that this example doesn't make the argument it claims to make.<p>Let's look at some code I'm writing now. Here is strstr:<p><pre><code> boo :: String -> String -> Int
</code></pre>
Not too helpful really. Here is a function which searches ComplexDataStructure, which contains file and directory names as well as other data, for partial matches of "string", returning a "goodness" value indicating the closeness of the match for the highest-matching candidate:<p><pre><code> boo :: ComplexDataStructure -> String -> Int
</code></pre>
I challenge anyone to work out what the function does from that. Sure, you can make more assumptions about the Haskell version, but, practically speaking, IO cleanliness has little to do with it. What matters here is knowing what the data structures do, and using decent types.