I'm a software architect/consultant in Boulder, Colorado. I started blogging at: http://wayne-adams.blogspot.com/, but have since started the new blog, Data Sceintist in Training which will cover the areas I am learning as part of my own "big data" training, including the Hadoop family, frameworks like OpenStack, the R programming language, column-oriented databases and the art of examining data sets for useful patterns. The original blog will be kept alive with Java-specific posts. Wayne is a DZone MVB and is not an employee of DZone and has posted 35 posts at DZone. You can read more from them at their website. View Full User Profile

Haskell From an OO Developer's Perspective, Part 1

10.27.2011
| 4719 views |
  • submit to reddit
I'm learning Haskell by following O'Sullivan, Goerzen and Stewart's Real World Haskell. I've been writing object-oriented code for well over half my career as a developer, and there are things about functional programming that really stand out to me specifically because of my OO background. My goal is to capture that experience as I learn, because I haven't been able to find much material that speaks to the unique experience of transitioning from OO to FP. So here goes.

As you can guess, functions are highly regarded in functional programming. There is an emphasis on "purity", something you don't hear much about in OO. Simply put, a pure function does its work without side effects. Repeatedly invoking a pure function with the same arguments will always yield the same result.

When you hear this topic discussed in FP, it frequently includes references to mutable state. For example, if invoking your function changes the state of a variable, your function is not pure. In fact, if your function even references a global variable, it is not pure. Why? Because you can't guarantee that invoking your function repeatedly, with the same arguments, will yield the same results, because it relies on state over which it has no control.

In functional programming, the goal is to keep code as pure as possible and to isolate impure code. One advantage of pure code is in testing, as you don't have to worry about the effect of other threads on the results produced by your code. In addition to code that employs mutable state, other examples of impure code are: any I/O, pinging a web service for that live data feed, and so on. As I go through my self-training, I will be very interested in how useful an FP application will be in my field. I write mostly middle-tier Java code with a lot of interfaces to web services, and I have to admit at this stage I'm a little skeptical. Will I write a big chunk of FP code that's 99% "impure" and feel that I just performed the equivalent of porting a Fortran program to C++? I hope not. But it's way too early to pass judgment, and I expect a far happier outcome.

Anatomy of a Haskell function

Functions in Haskell look a lot different than Java functions. I've spent a few months trying to become proficient in Erlang, and so the structure of an FP function is starting to become familiar to me. Here's an example Haskell function:

agentName code =
if code == 86
then "adams"
else if code == 99
then "feldon"
else "unknown"
Given an agent's code number, it returns the agent's (real) name. In general, a function consists of:
  • The name of the function
  • The argument names, separated by whitespace
  • The equals "=" sign
  • The expression that your function evaluates and returns
Note that the example does not have a return statement. In this example, the "if" statement itself is the value returned by the function. For this reason, you cannot leave an unaccounted-for branch of the if statement. In other words, if you try to load the following function definition into the interactive Glasgow Haskell compiler:
you will see the following:
agentName code =
if code == 86
then "adams"
else if code == 99
then "feldon"
     agentName.hs:7:1: parse error (possibly incorrect indentation)
the reason being that there are some inputs for which the function will not be able to return a value at all. If you've ever declared a non-void Java function and forgot to return a value from a branch of an if statement, then this error message seems reasonable, if not quite as informative.

If we go back to the original version of the function, we can test its behavior:
Prelude> :load agentName.hs
[1 of 1] Compiling Main             ( agentName.hs, interpreted )
Ok, modules loaded: Main.
*Main> agentName 86
"adams"
*Main> agentName 99
"feldon"
*Main> agentName 007
"unknown"
Note, in the examples, the indentation, which is required when a statement (in this case, the function definition) extends across a line boundary. The size of the indentation and the characters used (space, tab) are not important, as long as the indentation is there.

There is obviously a lot more to Haskell functions, of course. The above points are what stand out to me as a mostly-OO developer.

I've been using the Glasgow Haskell Compiler and, in the examples above, the interactive interpreter (and debugger) ghci. Although I'm generally following Real World Haskell, I don't really expect to review the entire book in slow-motion on a blog (who would read that?). So I may not write a post about defining types unless it seems unusually foreign to OO. My ultimate goal is to become proficient enough to provide useful and practical advice, oriented toward an OO developer wanting to learn to write production-quality FP code.

 

From http://wayne-adams.blogspot.com/2011/10/haskell-from-oo-developers-perspective.html

Published at DZone with permission of Wayne Adams, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)