A functional programming solution for Mr and Mrs Hollingberry

Hi all, I'm in the process of learning how to approach problems from a functional perspective, coming from an Object Oriented background (mostly Smalltalk). One of the general concerns/questions raised when talking to people in a similar position is: "How do I design/model a problem when I don't have my trusted classes and objects available?" With this in mind I've created a programming exercise where I imagine an OO programmer would use an object hierarchy with subtype polymorphism as part of the solution. And then I'd like to compare functional implementations of the same problem: https://github.com/apauley/HollingBerries I want to see how elegant a solution I can get in a functional language, given that the problem description is not really elegant at all. It has a few annoying exceptions to the normal rules, typical of what one might get in a real specification from some client. Currently there are 3 implementations: - one in Erlang, my attempt at implementing a functional solution - one in Ruby, my attempt to see how an object hierarchy could be used - one in Clojure, done by one of the people in our FP user group [1] I would love to include some Haskell implementations as well, if any of you are interested. Kind regards, Andreas Pauley 1. http://www.meetup.com/lambda-luminaries/ -- http://pauley.org.za/ http://twitter.com/apauley

Challenge accepted! I have written a solution in Haskell; please merge :)

Andreas Pauley
I want to see how elegant a solution I can get in a functional language, given that the problem description is not really elegant at all. It has a few annoying exceptions to the normal rules, typical of what one might get in a real specification from some client.
After taking a look at other solutions, I feel like I will have to explain myself, so I’d better do that without prompting :) - nothing was said about meaningful error messages, so I didn’t bother. - I had decided against defining constants like `supplier_markup_percentage_modification` separately; `PremiumSupplierIDs` and markup table are defined locally in the `calc` function, too. The latter two issues are fixed in the next version, as someone may consider them to be against elegance. - surprisingly, all solutions use explicit comparisons to determine the product category. While it is okay for continuous ranges of codes, it doesn’t scale and not really elegant. Fixed as well.

On Mon, May 21, 2012 at 12:54 AM, Artyom Kazak
Andreas Pauley
писал(а) в своём письме Sun, 20 May 2012 20:33:13 +0300: I want to see how elegant a solution I can get in a functional language, given that the problem description is not really elegant at all. It has a few annoying exceptions to the normal rules, typical of what one might get in a real specification from some client.
After taking a look at other solutions, I feel like I will have to explain myself, so I’d better do that without prompting :)
- nothing was said about meaningful error messages, so I didn’t bother. - I had decided against defining constants like `supplier_markup_percentage_modification` separately; `PremiumSupplierIDs` and markup table are defined locally in the `calc` function, too. The latter two issues are fixed in the next version, as someone may consider them to be against elegance. - surprisingly, all solutions use explicit comparisons to determine the product category. While it is okay for continuous ranges of codes, it doesn’t scale and not really elegant. Fixed as well.
Thanks, I've merged this. Had a quick look at the code, I like it :-) -- http://pauley.org.za/ http://twitter.com/apauley

On 21/05/2012, at 5:33 AM, Andreas Pauley wrote:
With this in mind I've created a programming exercise where I imagine an OO programmer would use an object hierarchy with subtype polymorphism as part of the solution.
Being unfamiliar with git, I've submitted an AWK answer by e-mail. I've used quite a few OO languages. I like to think that I *am* an OO programmer. But this exercise struck me from the beginning as something where classes would add nothing but bulk. As a fan of Smalltalk, I have to say that the Smalltalk version confirmed this for me; a Smalltalk solution for this exercise could be a lot smaller than that one if it _didn't_ introduce new classes.

On Wed, May 23, 2012 at 11:37 PM, Richard O'Keefe
On 21/05/2012, at 5:33 AM, Andreas Pauley wrote:
With this in mind I've created a programming exercise where I imagine an OO programmer would use an object hierarchy with subtype polymorphism as part of the solution.
Being unfamiliar with git, I've submitted an AWK answer by e-mail.
I have committed the awk version for those interested to see: https://github.com/apauley/HollingBerries/tree/master/awk/RichardOKeefe
I've used quite a few OO languages. I like to think that I *am* an OO programmer. But this exercise struck me from the beginning as something where classes would add nothing but bulk. As a fan of Smalltalk, I have to say that the Smalltalk version confirmed this for me; a Smalltalk solution for this exercise could be a lot smaller than that one if it _didn't_ introduce new classes.
Maybe this is an example of where we as an industry has been somewhat brainwashed. For many programmers it is difficult to envision coding pretty much anything without classes. Do you know of an exercise where classes would add value? Something fairly small, roughly similar in size to this exercise. -- http://pauley.org.za/ http://twitter.com/apauley

On 24/05/2012 18:56, Andreas Pauley wrote:
I've used quite a few OO languages. I like to think that I *am* an OO programmer. But this exercise struck me from the beginning as something where classes would add nothing but bulk. As a fan of Smalltalk, I have to say that the Smalltalk version confirmed this for me; a Smalltalk solution for this exercise could be a lot smaller than that one if it _didn't_ introduce new classes.
Maybe this is an example of where we as an industry has been somewhat brainwashed. For many programmers it is difficult to envision coding pretty much anything without classes.
Do you know of an exercise where classes would add value? Something fairly small, roughly similar in size to this exercise.
I don't. I think the trouble is that classes don't add value in exercises of this size. Nor do any similarly heavyweight Haskell engineering features like polymorphism or typeclasses. Just write the program and have done with it. Hard-code everything and you'd end up in C# with something not much different from the Haskell solutions on Github (except for the usual heavy syntactic overhead of C#). I'd say many of the programmers in my heavily OO-centric organisation would do just this: experience shows us that simple == flexible more often than not. However, it becomes more interesting if the requirements are thought likely to change in the future. More product lines? More suppliers? More or fewer troublesome or premium ones? More rules affecting pricing? Based on what other fields? How much is configurable at runtime and how much requires programmer time and recompilation? Are you likely to try and re-sell a similar system to another client and, if so, do you want to share code across clients to cut your support and maintenance overheads? More input formats? More output formats? Summary reporting? Interfaces with other systems? This is where classes start to become worthwhile, as (with the right architecture) they let you add to the behaviour of the system without changing existing working code. Of course, you can get a similar level of flexibility in a functional setting but it looks different. In OO languages it's easy to add new subtypes but adding a new method to a base type is a pain (as each subtype has to be changed). Conversely in functional languages it's a pain to add new constructors to a datatype (as all your pattern matching and case expressions need alteration) but easy to add new functions operating on your datatypes. So this pushes me in different architectural directions in the two settings - I try and make expected new requirements involve adding classes in an OO language, but they should involve adding new functions in my Haskell programs. Cheers, David

On 26/05/2012, at 4:16 AM, David Turner wrote:
I don't. I think the trouble is that classes don't add value in exercises of this size.
This was the key point, I think. In this example, there wasn't any significant behaviour that could be moved to superclasses. For that matter, whether a supplier is plain, preferred, or problematic is, one hopes, not a *permanent* property of a supplier. Sometimes higher-order functions can substitute for classes.

On Sun, May 27, 2012 at 7:07 PM, Richard O'Keefe
On 26/05/2012, at 4:16 AM, David Turner wrote:
I don't. I think the trouble is that classes don't add value in
exercises of this size.
This was the key point, I think. In this example, there wasn't any significant behaviour that could be moved to superclasses. For that matter, whether a supplier is plain, preferred, or problematic is, one hopes, not a *permanent* property of a supplier.
Sometimes higher-order functions can substitute for classes.
Functors can always substitute for OO classes. A class system is a functor from the set of objects to a set of methods, mediated by inheritance, or things like message-passing, duck typing, prototyping, etc. Functions with the type Foo -> Foo can be easily used to implement a prototype based dispatch mechanism. Indeed, this is a common Haskell pattern. Define: -- Library code: defaultFoo :: Foo defaultFoo = Foo { bar = ..., baz = ... } -- Client code myFoo = defaultFoo { bar = myBar } Things can get as complicated as you would like, up to and including inheritance, by using functors other than ((->) a) The defining characteristic of OO is that objects are stateful, but self-contained entities. How methods are defined and dispatched vary wildly across OO languages.

I added a Scala solution since Haskell is already well represented.
Regarding exercises that are easier in OO, I don't think you'll find one
that a good Haskell programmer can't match in a functional style. But if
you make simulation the goal of the exercise (rather than writing a program
that takes input and produces the correct output however it likes), you'll
get a nice compare/contrast of OO and non-OO approaches.
One idea (contrived and silly though it is) is modeling a Courier that
delivers message to Persons. There is a standard default reply for all
Persons, some individuals have their own default reply, and there are
conditional replies based on the sender. Each reply has the ability to
alter a Person's mood. The goal of the exercise would be to read in a CSV
file in the form of "To, From, Message", and then output the interactions
based on rules. A sample run might look like:
Courier delivers "let's have lunch" from Susan to Joe
Joe replies "Thanks for the message!"
Courier delivers "how's your day?" from Joe's Best Friend to Joe
Joe replies "Hey Best Friend, thanks for the message!"
Joe's mood changes from "normal" to "happy"
This would be a trivial exercise for any OO programmer, and I suspect
solutions in different OO languages would look pretty much the same. But in
pure functional programming there are more choices to make (particularly
the choice of data structures and types), so you might see a wider range of
creative approaches.
On Sun, May 27, 2012 at 8:21 PM, Alexander Solla
On Sun, May 27, 2012 at 7:07 PM, Richard O'Keefe
wrote: On 26/05/2012, at 4:16 AM, David Turner wrote:
I don't. I think the trouble is that classes don't add value in
exercises of this size.
This was the key point, I think. In this example, there wasn't any significant behaviour that could be moved to superclasses. For that matter, whether a supplier is plain, preferred, or problematic is, one hopes, not a *permanent* property of a supplier.
Sometimes higher-order functions can substitute for classes.
Functors can always substitute for OO classes. A class system is a functor from the set of objects to a set of methods, mediated by inheritance, or things like message-passing, duck typing, prototyping, etc.
Functions with the type Foo -> Foo can be easily used to implement a prototype based dispatch mechanism. Indeed, this is a common Haskell pattern. Define:
-- Library code: defaultFoo :: Foo defaultFoo = Foo { bar = ..., baz = ... }
-- Client code myFoo = defaultFoo { bar = myBar }
Things can get as complicated as you would like, up to and including inheritance, by using functors other than ((->) a)
The defining characteristic of OO is that objects are stateful, but self-contained entities. How methods are defined and dispatched vary wildly across OO languages.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

On 30/05/2012, at 10:16 AM, Eric Rasmussen wrote:
One idea (contrived and silly though it is) is modeling a Courier that delivers message to Persons. There is a standard default reply for all Persons, some individuals have their own default reply, and there are conditional replies based on the sender. Each reply has the ability to alter a Person's mood. The goal of the exercise would be to read in a CSV file in the form of "To, From, Message", and then output the interactions based on rules.
Simulation is of course what Simula 67, the first well known object oriented language, was devised for. Simula 67 was also one of the first three languages I know of to include concurrency as a standard feature, the others being PL/I and Algol 68. And to an Erlang programmer, the obvious way to model a simulation is with one process per entity. It's also not accidental that Smalltalk has had concurrency since it first appeared, and the simulation example in the Blue Book (and the simulation library derived form it) makes essential use of concurrency. In ML I would use the Concurrent ML facilities (supported in SML/NJ and MLton). Using Haskell I would definitely consider simulation using concurrency. And objects per se might not be all that useful. In F# I would expect to use threads but not classes.

Andreas Pauley
Do you know of an exercise where classes would add value? Something fairly small, roughly similar in size to this exercise.
AFAICR, the motivating example for OO (in Simula) was simulating an environment where different entities interact - I think the case was queues in a post office, where object represents the door, customers, tellers, etc. Perhaps something along those lines? -k -- If I haven't seen further, it is by standing in the footprints of giants
participants (7)
-
Alexander Solla
-
Andreas Pauley
-
Artyom Kazak
-
David Turner
-
Eric Rasmussen
-
Ketil Malde
-
Richard O'Keefe