
Haskell is referentially transparent. This enables a whole host of program reasoning and compiler optimization techniques that you can't get in languages without this property; it's hard to explain why it is good until you've been bitten by code that *isn't*. One big consequence of referential transparency is that a whole host of complicated optimizations in other languages are replaced with simple inlining. So one question is, what does this program do?
main = print (count id [id])
The compiler might decide to inline the first id:
main = print (count (\x -> x) [id]) which then, if we are comparing "machine addresses", means they are not equal.
I am sure you agree that code that stops working depending on the
optimization settings of the compiler is a scary thing!
In scheme, which is not referentially transparent, there are several
equality primitives. One checks "object identity", whereas another
goes into the depths of any structure it is passed and compares the
innards. In Haskell, there is *no* concept of "object identity. It
just doesn't exist! This means there is no observable difference
between 1 and (length [ "hello" ]). There's no observable difference
between const and (\x y -> x).
In order to make this work, but still be able to use == (which
everyone wants), == requires its arguments to be of a type that is
comparable for equality; that's what the error message from ghci is
saying:
On Sat, Apr 18, 2009 at 9:27 AM, michael rice
No instance for (Eq (a -> a -> Bool)) arising from a use of `==' at <interactive>:1:0-13
-- ryan