[Haskell-cafe] Re: OOPer?
Ryan Ingram
ryani.spam at gmail.com
Tue Nov 18 02:39:15 EST 2008
David,
I had to bring up a parenthetical from your message because I think it
is often a point of confusion:
2008/11/17 David Leimbach <leimy2k at gmail.com>:
> (Would it then be fair to equate a Haskell class to a Java Interface, but not
> to a Java class?)
This is a dangerous direction to go, because while there are some
analogies, going this direction leads to many mistakes.
A typeclass is similar to an interface, in that it defines the
operations on some object, and you can call functions that use that
typeclass polymorphically over any instance. But in the OOP model,
interfaces are also a form of existential quantification. If I have
an IPrintable object, I can put it on a list of IPrintables:
> // psuedo-java:
> List<IPrintable> foo(List<IPrintable> tail)
> {
> String x = "hello"; // assume String is an instance of IPrintable
> return List.cons(x, tail);
> }
But in Haskell, this function doesn't typecheck:
> foo :: Show a => [a] -> [a]
> foo xs = "hello" : xs
The type of "foo" says that its argument is a homogenous list of
*some* instance of Show, but it doesn't specify which one. Of course,
in Haskell you can make this work with existential types:
> data AnyShow = forall a. Show a => ExistentialShow a
> foo2 :: [AnyShow] -> [AnyShow]
> foo2 xs = ExistentialShow "hello" : xs
> foo3 :: Show a => [a] -> [AnyShow]
> foo3 xs = foo2 (map ExistentialShow xs)
There are a few other differences; for example,
> poly :: Num a => a
> poly = fromInteger 1
The person *calling* poly determines what instance of Num they want
returned; in OOP, poly would have to be called with a "factory" as an
argument that told it how to construct the instance of the Num
interface that the caller wants. This generalizes to code that would
be much more difficult to write in an OOP style; consider:
> poly2 :: Num a => a -> a
> poly2 x = x + 1 -- in Haskell, 1 here is implicitly 'fromInteger 1'
This is surprisingly hard to write in an OOP language, and almost
certainly uglier than the Haskell solution. Either the arguments to
plus have to be polymorphic, which is really difficult, or you need a
special version of every operator that takes an Integer instead of the
class in question, or you need some way to query the class for a
factory which builds an instance of the class.
In Haskell, (+) specifies that the arguments must be the same type,
unlike the OOP solution where one argument is given privledged status
as the method receiver.
-- ryan
More information about the Haskell-Cafe
mailing list