I've been thinking about the way Haskell picks out an implementation of a function that's defined on a type. F.i. the way the type of mappend is defined on the type Monoid. But the implementation is defined on an instance of Monoid. So when we use mappend the implementation is found by looking up the implementation of the runtime type of the Monoid.
glueTwice:: Monoid m => m -> m
glueTwice m = m `mappend` m
glueTwice "bla" -- uses mappend implementation of List
This seems very much like the key point of OO: the Liskov substitution principle and like having an interface Monoid that's implemented by String.
So what's different between OO and these functions defined on types and implemented on instances?
The only thing I can come up with is the mantra "an object has identity, state and behaviour". I guess that Haskells tendency to memoization means that a string doesn't have identity.