Skip to content

object oriented

These are the stories that have been posted to the object oriented category.

F# and Haskell, Estranged Cousins


Published to Rick Minerich's Development Wonderland by Richard Minerich January 29, 2009 20:24

In this post I compare and contrast Haskell and F#.  It may come as no surprise that with so much shared history they share so much in common.  However, it’s interesting to consider how the perspectives of the languages’ developers play a large role in determining the differences between the languages.

 

A Shared History

As far as the family tree of functional programming is concerned, F# and Haskell are not too distant cousins. haskellandfsharphistory

They both share a very similar syntax as well as a large number of features.  A great example of this is Hindley–Milner type inference. 

ML was the first widely used language to leverage Hindley–Milner for static inferred typing, a feature to which it owes much of it’s success.  However, almost all functional programming languages now also have this feature.  The FP community has always been fast to adopt obviously useful features.  Some other things that fit into this category are garbage collection (Lisp) and lazy evaluation (Lazy ML).

The most obvious difference between Haskell and F# is somewhat easy to infer from this graph: object oriented constructs.  That is to say, OCaml pioneered the use of object oriented data structures in functional programming and F# is it’s direct descendant.  This has made OCaml (and in turn F#) somewhat of a black sheep in the theoretical functional programming world. 

The reason many functional programming theorists dislike objects is because they want a language based on math.  Unlike the majority of the ideas in functional programming, objects don’t have roots in either lambda calculus or category theory.  However, this has not stopped OCaml from being successful.  In fact, quite the opposite. 

The use of objects mitigates one of the largest roadblocks in the path to functional programming adoption by engineers:  the difficulty inherent in organizing large functional programs.  The OCaml language engineers also showed that leveraging the object oriented paradigm did not hamper their ability to use static analysis techniques.  Because of this OCaml approaches the speed of C

While it is not pure, OCaml is almost an ideal compromise between theory and engineering.   Indeed, nothing approaches it in terms of a functional language which fits into the paradigms of the Microsoft .NET framework.  It’s easy to see why Microsoft chose to extend OCaml when building a functional language to bring to it’s software engineering masses.

On the other hand, Haskell is almost the ideal language for academic exploration of functional programming.  The fact that it’s strictly limiting in terms of side effecting and adherence to abstract mathematical concepts means no side effecting surprises.  Also, the fact that it’s a committee language means that if a researcher can get enough support for an idea, they can almost be sure it will be included in the next iteration of the language.

 

Haskell as a Committee Language

Repeat the mantra after me:  Haskell is Lazy; Haskell is Pure; Haskell has Type Classes; Haskell is a Committee Language.

Of all of these, the most defining characteristic of Haskell is that it is a committee language.  It’s an amalgamation of many different goals with no clear vision.  This is at the same time Haskell’s greatest strength and greatest weakness.  While it is the most widely used pure functional programming language, the quirks of committee design are obvious.

Some I ran into within two hours of starting with Haskell:

The first was integer rollover.  Haskell has two integer datatypes: integer and int.  Integer is infinitely sized but can be quite slow to use and due to that, it’s rather infrequently used.  On the other hand int is fast but, just like in C, can roll over. There is no way to check the overflow bit.

So, ints can roll over, I can accept that.  What it implies to me is that speed is more important to Haskell than robustness.  However, this brings me to my second point:  Many basic list operations will throw errors on an empty list.  This seems entirely inconsistent to me. 

I understand that if they didn’t, a logic error would be much more likely to cause an infinite loop in a tail recursive function.  However, this seems completely at odds with the “speed first” definition of an int.  It also means that almost everyone ends up wrapping the default list operations with the Maybe monad.

The third issue was that operations with the float data type are slow.  Real World Haskell suggests always using a double due to the fact that a great deal of focus has gone into optimizing double arithmetic but very little into floats.  This demonstrates another thing that comes about with committee languages: often things as important as optimization of basic data types can fall through the cracks because everyone involved wants to work on more exciting things.

Please don’t misunderstand me here, I really like Haskell.  I’m hard on it because I can see that it has a great deal of unrealized potential.  If Haskell is to be a language used for real software engineering, the committee needs to sit down and think hard about an overarching vision for the project.

 

What is the goal here?

The biggest difference between the world of theorists and the world of engineers is that each group has an entirely different set of concerns.

Theorists want to implement ideas fast so that they can crank out papers fast.  A large part of this is having a language that is very close to math so that implementing ideas directly from the chalkboard is trivial.  As the theory world changes so fast, they don’t often care much about organization or maintainability. 

As the committee responsible for Haskell is mainly made up of theorists, it’s easy to see why the language has taken the direction it has.  It’s a language that is very close to math.  As the lifecycle of most academic code is very short, small implementation details which might cause a reduction in robustness are less important.

Engineers want to minimize time spent maintaining code.  Part of this is having a language that emphasizes safety in that it facilitates catching as many bugs as possible, as early in the process as possible.  Another important part of this is code organization as every moment that is spent trying to find a bug is a moment spent not fixing it.  As the cost of maintaining software generally dwarfs the initial development cost, development speed must take a back seat to testing and organization.

The syntax heavy C# is a great example of this.  It’s slow to write in but provides many constructs for the organization and testing of code.  On top of this a great number of design patterns exist to further categorize substructures in a computer program.  C# is slow to write, but it’s relatively safe and mountains of patterns and best practices have been made to guide it’s developers.

However, we in the software engineering world are in the midst of a crisis.  It turns out that traditional imperative object oriented programs do not lend themselves to heavy parallelization.  Yet, parallelize we must.  We are looking at exponential growth in the number of cores contained in each processor. Because of this we engineers find ourselves at a bit of an impasse.  Those that are looking ahead know…

Engineers will soon want very badly to minimize time spent maintaining parallelized code.  We need our programs to be easy to organize, manage and test.  Yet, as we will soon need to deal with massively parallelized systems, we find many of our ideas about what makes code robust and maintainable are broken.  At the same time, to move to a purely functional language means leaving behind years of thought on how computer programs ought to be constructed, tested and maintained.  Having any pattern, even if it’s wasteful or has many corner cases, is much better than having none.  This is why a hybrid language is so important.

OCaml and F# provide engineers with the set and forget concurrency that comes along with the functional tradition.  At the same time these languages have all of the organizational constructs of object oriented programming as well.  This means that we can continue to use the same types of large scale organizational structures in our programs and also gain the safe parallelism that implicit immutability provides.

 

Conclusion

And so we see that it’s important to consider a language in terms of how it’s creators envisioned it’s use.  Haskell has been developed mainly with research in mind and so is a fantastic research language.  F# has been developed mainly with engineering in mind and so is much better suited for engineering.

In understanding this it’s also easy to see that comparing Haskell to F# is like comparing the tools of a physicist to those of an engineer.  They may have much in common superficially, but they are designed with much different ends in mind.

 

Links

A History of Haskell: Being Lazy with Class
Tutorial: OCaml for Scientific Computation (Contains some history)

Why OO may not suck, or, Take a ride on the Falsus Omnibus


Published to Rick Minerich's Development Wonderland by Richard Minerich February 11, 2009 11:00

This post is in response to Joe Armstrong’s Why OO Sucks.  While I feel that Joe’s post reads more like an sermon than a stream of rational thought, it does bring up a number of misconceptions I feel many people in the functional programming world share and which need to be discussed openly if it and the object oriented world are to come to terms and work together.

The main issue here is that, in the minds of many functional programming advocates, the concept of an object is inseparable from the amalgamation of 30 years of different, and sometimes contradictory, object oriented programming ideologies. 

Perhaps they don’t understand that when binding these ideas together for the sake of argument they are simply constructing a straw man.  Similarly, to say that we must either have all of the history of object oriented design or pure functional programming, is a false dichotomy.  We can have either, neither, both separately, or any number of combinations of ideas from both groups.

 

Now, lets address each of Joe’s objections from a somewhat more moderate perspective.

In Response to “Objection 1 – Data Structure and functions should not be bound together.”

I disagree with Joe’s logic here.  It does not follow that because functions and data structures are “different animals” that they should “not be kept in the same cage”.  Wouldn’t having functions be first class citizens be locking them in the same cage with data structures as well?  The fact that they do share some fundamental similarity is manifest in that most functional programming languages do not treat function and data structure in a fundamentally different way. 

Also, I have seen no compelling reason as to why it is wrong to couple transformations with the data structure that they are able to be applied to.  When transformations often have to be tailored specifically for a particular data structure, why would we not keep them strongly associated with said data structure.

 

In Response to “Objection 2 – Everything has to be an object.”

As I discussed in my introduction, this is simply not true in all languages which support objects.

 

In Response to “Objection 3 – In an OOPL data type definition are spread out all over the place.”

First of all, it should be immediately obvious to anyone who works on even medium sized projects that having many types defined in the same file is a very bad thing.  The core of the issue is that it makes group collaboration quite difficult.

Secondly, any system that has ubiquitous data structures can’t be very large otherwise the namespace would become quite cluttered.  In large systems this cannot be mitigated by simply saying “more functions, fewer data structures”.

Finally, to state that any object which operates on another must inherit from it is a completely incorrect statement.  In the modern object oriented world it is common to have objects which exist solely to build, process or interface with other objects.  Also, as I mentioned above, it’s entirely possible to have stateless objects which are simply data structures which are bundled with a collection of predefined transformations.

 

In Response to “Objection 4 – Objects have private state.”

First of all, state is not the root of all evil.  While it may be harmful to concurrency and static analysis, there are many stateful algorithms which perform much better than their stateless counterparts.

Secondly, it’s entirely possible to have immutable objects.  Perhaps in these objects some state is hidden for the sake of representing ideas in a simple manner, perhaps not.

Finally, as to information hiding in general, in large systems it’s very easy to be overwhelmed by the quantity of information.  If you can say via testing “I can trust this structure over here” it means it’s entirely possible to ignore that and focus work on another piece of the system.  It’s also important to note that functional programming languages often have information hiding systems of their own.  In the most base case, calling other precompiled functions amounts to information hiding and comes along with all of the negative things stated in this section.

 

In Response to “Conclusion – Why OO was popular.”

It seems to me here that if you removed all instances of “It was thought” this would be a somewhat correct summarization. 

In reality, the industry has been using object oriented programming for many more reasons than what has been listed here.  A particularly strong reason is that it supplies an organizational framework for data structures and functions which simply does not have an equivalent in the pure functional programming world.

 

Conclusion

I must apologize to Joe here.  I don’t intend to pick on him in particular.  However, I had never previously seen a post in which the the most common misconceptions around object oriented programming were so plainly stated.

To say that the concept of an object and that the collections of ideologies used commonly to construct programs using objects are somehow inseparable is completely false.  To further state that the only reasonable choice is to instead move to pure functional programming bears no additional truth.  Yet they are both pieces of constantly perpetuated misinformation. 

The fundamental idea that data and function can be bound for the sake of organization still holds and does not inherently violate any of the tenants of functional programming.  In terms of the organizational structure of our programs we have gained much from objects.  Why then should we abandon them without sufficient reason?  It seems to me that it would be a mistake to dismiss all of what we have gained for baseless ideological reasons alone. 

Why OO may not suck, or, Take a ride on the Falsus Omnibus


Published to Rick Minerich's Development Wonderland by Richard Minerich February 11, 2009 11:00

This post is in response to Joe Armstrong’s Why OO Sucks.  While I feel that Joe’s post reads more like an sermon than a stream of rational thought, it does bring up a number of misconceptions I feel many people in the functional programming world share and which need to be discussed openly if it and the object oriented world are to come to terms and work together.

The main issue here is that, in the minds of many functional programming advocates, the concept of an object is inseparable from the amalgamation of 30 years of different, and sometimes contradictory, object oriented programming ideologies. 

Perhaps they don’t understand that when binding these ideas together for the sake of argument they are simply constructing a straw man.  Similarly, to say that we must either have all of the history of object oriented design or pure functional programming, is a false dichotomy.  We can have either, neither, both separately, or any number of combinations of ideas from both groups.

 

Now, lets address each of Joe’s objections from a somewhat more moderate perspective.

In Response to “Objection 1 – Data Structure and functions should not be bound together.”

I disagree with Joe’s logic here.  It does not follow that because functions and data structures are “different animals” that they should “not be kept in the same cage”.  Wouldn’t having functions be first class citizens be locking them in the same cage with data structures as well?  The fact that they do share some fundamental similarity is manifest in that most functional programming languages do not treat function and data structure in a fundamentally different way. 

Also, I have seen no compelling reason as to why it is wrong to couple transformations with the data structure that they are able to be applied to.  When transformations often have to be tailored specifically for a particular data structure, why would we not keep them strongly associated with said data structure.

 

In Response to “Objection 2 – Everything has to be an object.”

As I discussed in my introduction, this is simply not true in all languages which support objects.

 

In Response to “Objection 3 – In an OOPL data type definition are spread out all over the place.”

First of all, it should be immediately obvious to anyone who works on even medium sized projects that having many types defined in the same file is a very bad thing.  The core of the issue is that it makes group collaboration quite difficult.

Secondly, any system that has ubiquitous data structures can’t be very large otherwise the namespace would become quite cluttered.  In large systems this cannot be mitigated by simply saying “more functions, fewer data structures”.

Finally, to state that any object which operates on another must inherit from it is a completely incorrect statement.  In the modern object oriented world it is common to have objects which exist solely to build, process or interface with other objects.  Also, as I mentioned above, it’s entirely possible to have stateless objects which are simply data structures which are bundled with a collection of predefined transformations.

 

In Response to “Objection 4 – Objects have private state.”

First of all, state is not the root of all evil.  While it may be harmful to concurrency and static analysis, there are many stateful algorithms which perform much better than their stateless counterparts.

Secondly, it’s entirely possible to have immutable objects.  Perhaps in these objects some state is hidden for the sake of representing ideas in a simple manner, perhaps not.

Finally, as to information hiding in general, in large systems it’s very easy to be overwhelmed by the quantity of information.  If you can say via testing “I can trust this structure over here” it means it’s entirely possible to ignore that and focus work on another piece of the system.  It’s also important to note that functional programming languages often have information hiding systems of their own.  In the most base case, calling other precompiled functions amounts to information hiding and comes along with all of the negative things stated in this section.

 

In Response to “Conclusion – Why OO was popular.”

It seems to me here that if you removed all instances of “It was thought” this would be a somewhat correct summarization. 

In reality, the industry has been using object oriented programming for many more reasons than what has been listed here.  A particularly strong reason is that it supplies an organizational framework for data structures and functions which simply does not have an equivalent in the pure functional programming world.

 

Conclusion

I must apologize to Joe here.  I don’t intend to pick on him in particular.  However, I had never previously seen a post in which the the most common misconceptions around object oriented programming were so plainly stated.

To say that the concept of an object and that the collections of ideologies used commonly to construct programs using objects are somehow inseparable is completely false.  To further state that the only reasonable choice is to instead move to pure functional programming bears no additional truth.  Yet they are both pieces of constantly perpetuated misinformation. 

The fundamental idea that data and function can be bound for the sake of organization still holds and does not inherently violate any of the tenants of functional programming.  In terms of the organizational structure of our programs we have gained much from objects.  Why then should we abandon them without sufficient reason?  It seems to me that it would be a mistake to dismiss all of what we have gained for baseless ideological reasons alone. 

Code Camp 12: Boston – Why F#?


Published to Rick Minerich's Development Wonderland by Richard Minerich October 16, 2009 15:18

A couple of months ago I was talking to Lou Franco, the head of our Software Engineering department and fellow functional programming enthusiast, about the possibility of using F# for projects in the future.  Being business minded, he replied that he would need a compelling reason to bring F# on board.  This presentation is dedicated to him and others who have functional programming on their radar but haven’t yet found a compelling reason to bring it in to their company.

I acknowledge that, as for now, it’s difficult to suggest anyone do more than play with F#.  I have been anxiously awaiting the stabilization of the F# API which will come along with the release of VS2010.  With the recent changes breaking backwards compatibility, maintaining my old F# samples has become quite a nightmare.  Indeed, not a single code sample I have from a year ago works out of the box with the current release.

However, VS2010 is only a few months away.  Now is the time to start learning about F# and the paradigms which make it so powerful.  Functional programming has amazing benefits in terms of parallelization, code compression and overall code robustness.  

At Code Camp 12 Boston, I will talk about the soon-to-be-realized world where programmers are divided into groups which each use different types of languages to build different kinds of things.  This is easy to predict as it is already occurring.  UI, data processing and data storage programmers are already diversifying both in working knowledge and tools.

As is evidenced by WPF, HTML and CSS it seems UI design is moving more and more to a declarative style.  Similarly, the rise of F#, Scala, Erlang and Haskell indicates that algorithmic programmers are migrating to the functional programming languages.  SQL has long been the language of those involved in data storage.  It’s no wonder that this has happened.  When your tool is better designed for your job, the work gets done faster and you end up with a better result.

Where does this leave imperative and object oriented languages?  Languages like Java, VB and C# will be relegated to being used as “glue” for existing systems while abstract languages slowly eat away their market share.  This will happen more and more as the number of cores per processor continues to increase and those with imperative implementations find that they are unable to scale.

When: Oct 16th, 2009 (11:50am)
Where: 201 Jones Rd, 6th Floor, Waltham MA USA (Room TBC)

Slides are available here.

Also, be sure to also check out my fellow F# User Group leader Talbott Crowell’s talk.  It’s right before mine (10:30) in the same room (Thanks Chris!).  You can find out more by heading over to Chris Bowen’s blog and reading his post on Code Camp 12.