Does Haskell support object oriented programming

22,402

Solution 1

How do you separate declaration and implementation in Haskell?

In Haskell you can define a typeclass, which is rather different from an object oriented class so don't let the name fool you. Using the keyword class, you can declare function names and type signatures which can be instantiated (implemented) elsewhere for a particular data type.

For example, the Hashable typeclass defines the hash function, which can turn any instantiated data type into an Int. Have a new, funky data type you want to be able to hash? Fine, make an instance of Hashable. The most common data types are instantiated by the module that defines Hashable (see the linked documentation for 'Instances').

Typeclasses aren't the only way to define an interface. A method that is often under-rated is a plain old data structure. Because Haskell has first class functions, you can define a data structure that has functions as fields:

data ShuttleInterface =
  SI { launch    :: Delay -> IO Handle
     , deploy    :: Payload -> IO ()
     , getStatus :: IO Status
     }

And your functions can build or consume this data structure:

deployAllSensors :: ShuttleInterface -> IO ()
deployAllSensors shuttle = do
    status <- getStatus shuttle
    let notDeployed = filter (not . deployed) (sensors status)
    when (isOrbiting status) (mapM_ deploySensor notDeployed)

-- we used the well-known Haskell functions: filter, not, , when, mapM_
-- and some supporting functions were assumed:
isOrbitting :: Status -> Bool
deploySensor :: Sensor -> IO ()
sensors :: Status -> [Sensor]
deployed :: Sensor -> Bool

How do you restrict access to data in Haskell?

To provide abstraction, Haskell uses Algebraic Data Types. To protect fields developers declare a data type but don't export it's constructors - instead they only export a set of safe primitives that maintain desired invariants.

For example, the Map module provides a balanced tree. It couldn't guarantee balance if anyone could just declare a Map using the primitives of Branch and Leaf, so the makers didn't export those. Construction of a map must rely on what is exported from Data.Map (and those have access to/use the constructors by virtue of being in the same module) such as fromList, empty, singleton, and a whole bunch of modifiers.

Solution 2

See Haskell's Overlooked Object System by Oleg Kiselyov and Ralf Laemmel for a detailed explanation of how OO concepts can be implemented in Haskell. But as Antal said in the comments, don't try to write a Java program in Haskell.

Remember that objects are a poor man's closure, and closures are a poor man's object.

Solution 3

Type classes are indeed the only constructs that remind remotely on OO concepts - in this case, on interfaces. Though, unlike in java, type classes are not types.

One good thing about type classes is that I can make totally unrelated, already existing types members of a type class. Whereas in java, sometimes one thinks: These classes A from package org.a and B from com.b that I am using ought really be implementing interface Y from a third package, but there is no way to do it that would not require a lot of boilerplate code, additional indirections, marshalling etc.

BTW, as an elderly programmer I'd like to note that "separation of declaration and implementation" has per se nothing to do with OOP. Just because most OO-langugaes support it does not mean the concept was not well known for a long time before OO was invented. Interested youngsters who think that programming before mainstreaming of OO must have been on a "stone age" level may look up MODULA, for example, where separation of declaration and implementation is not only possible, but enforced by the language.

Solution 4

One thing might be good to mention is lenses. They allow you to write the kind of a.b.c.d.e "expression" in a compose-able way.

The . can be defined for each data structure. So in some sense the . is a first class citizen in Haskell. It can be named, stored, two .-s can be composed, etc.

Share:
22,402

Related videos on Youtube

strider
Author by

strider

Updated on March 12, 2020

Comments

  • strider
    strider almost 4 years

    Does it support concepts like separation of declaration and implementation (interfaces and classes in Java)?

    How about restricting access (like access modifiers in Java)?

    • Antal Spector-Zabusky
      Antal Spector-Zabusky almost 13 years
      Note that if you're working in Haskell, you shouldn't try to write a Java program, and vice versa. Working with the language, instead of against the grain, will generally produce cleaner code.
    • Chris Smith
      Chris Smith almost 13 years
      There are some great answers below, but I'd suggest you not think of things like this as "OO" features. In Haskell, for example, the main unit of encapsulation and hiding of implementation is the module, and is not tied to any specific data structure. Modular design was a good thing before it was ever used in object oriented programming! Similarly, type classes in Haskell specifically reject the OO-ish idea of writing the data structure and its behaviors in one place, but still effectively separate interface and implementation.
  • Ingo
    Ingo almost 13 years
    +1, Perhaps it is good to point out that, since all data is immutable, protection of fields is, though possible, not nearly as important as in OOP languages with mutable data types.
  • acorello
    acorello almost 13 years
    Can you please explain better what do you mean with "Object's are poor man's closure" and vice-versa? I think closure as a nested function that has access to the variables declared in the outer scope. An object instead seems to define an opaque boundary between the code that sits in it and the outer world... With this in mind I can't understand what you mean. :/
  • Paul Johnson
    Paul Johnson almost 13 years
    You can think of a closure as a one-method ad-hoc object; just like an object it wraps up a bunch of data with a dynamically bound function that is going to use it. So to an OO programmer a closure looks a bit like a very limited kind of object. On the other hand if you want to create a closure-like thing in Java then you need to create a special base class and then a new descendant for every version of the closure. So from a functional programmer's point of view an object looks like a very clumsy and mandraulic kind of closure.
  • Phob
    Phob over 12 years
    Or maybe objects and closures provide the same functionality and we're all poor men ;-)
  • Dylan
    Dylan over 10 years
    @PaulJohnson Your link is broken. Can you give the actual name of the paper?
  • carlosayam
    carlosayam over 9 years
    @dylan, I believe Paul J. was referring to "Haskell's overlooked object system", which one can reach here from arXiv.org.
  • Anderson Green
    Anderson Green over 9 years
    I found another useful example of "OOP-like" syntax in Haskell: stackoverflow.com/questions/24235757/…
  • Ellen Spertus
    Ellen Spertus almost 9 years
    I edited the comment to include the name of paper and link, per @caya 's helpful comment.
  • Sled
    Sled over 8 years
    @Ingo what is necessary is not the ability to prevent modification, but the ability to prevent depending on. Like sun.misc.Unsafe has shown. Arguably, OOP is about abstracting the internals.
  • Alexander Feterman
    Alexander Feterman over 8 years
    Hiding implementation details in modules is still good practice even if you have immutability.
  • Evi1M4chine
    Evi1M4chine over 7 years
    It is very important, to note, that type classes are NOT a replacement for OO classes or OO interfaces (like in Java)!! They may be named and look alike, but thinking you can use one for the other will end you up in a huge mess. Trust me; I went down that road.
  • semicolon
    semicolon over 6 years
    @Evi1M4chine I mean anything you can do with an OO interface can be done with a typeclass, plus a hell of a lot more. So you kind of can just use them as a replacement for Java interfaces 99% of the time and be very happy with the huge increase in power.

Related