Functional Programming Architecture

Viewed 14714

I'm familiar with object-oriented architecture, including use of design patterns and class diagrams for visualization, and I know of service-oriented architecture with its contracts and protocol bindings, but is there anything characteristic about a software architecture for a system written in a functional programming language?

I know that FP has been used for medium-size to large scale projects. Paul Graham wrote the first incarnation of Yahoo! Store in Common Lisp. Some lisp development systems are complex. Artifical intelligence and financial systems written in functional languages can get pretty big. They all have at least some kind of inherent architecture, though, I'm wondering if they have anything in common?

What does an architecture based on the evaluation of expressions look like? Are FP architectures more composable?

Update: Kyle reminded me that SICP is a good resource for this subject.

Update 2: I found a good post on the subject: How does functional programming affect the structure of your code?

7 Answers

The common thread in the "architecture" of projects that use functional languages is that they tend to be separated into layers of algebras rather than subsystems in the traditional systems architecture sense.

For great examples of such projects, check out XMonad, Yi, and HappS. If you examine how they are structured, you will find that they comprise layers of monadic structure with some combinator glue in between.

Also look at The Scala Experiment paper which outlines an architecture where a system is composed of components that abstract over their dependencies.

The largest commonality you'll find in functional languages is using functions to store data. It's a bit like using accessor functions on an object without the object. Instead, the function is created in an environment where it has access to the data it needs. Now this function can be passed and used anywhere and still retain the ability to use the data.

Here's a very simple example. This isn't purely functional as it does change state, but it's common enough:

(define (make-counter)
  (let ((count 0))
    (lambda ()
      (set! count (+ count 1))
      count)))

(define x (make-counter))

(x) returns 1

(x) returns 2

...etc...

So we have a function, make-counter, that returns another function that has the state of the counter inside. We can call that newly created counter and observe the change inside.

This is how functional programs are structured. You have functions that take functions as arguments, you have functions that return functions with hidden state, etc. It's all a lot cleaner than managing memory yourself.

I printed out and looked over Design Patterns in Ocaml, and they use modules and functors (and objects) to recreate the normal design patterns we are used to. It's interesting, but I think they use objects too much to really see the benefit of functional languages. FP is very composable, part of it's nature. I guess my short answer is to use modules and functors.

My current project is pretty big, and we separate each module by files --implicit in ocaml. I've been hunting for a comprehensive resource as well that might have some alternative views or some thoughts on a really successful design that came out of a project.

I have worked with some fairly large functional projects. They usually fall into two camps (at least, the ones I have used):

  • Extreme scalability/reliability/concurrency. Transactional models can be built very tightly into the language. Concurrent ML is a great example of this, and projects that use it are very hard to get wrong when it comes to concurrency correctness.
  • Parsing/modifying frameworks. Many of the design patterns that these frameworks are based on are incredibly easy to formulate/build/modify in functional languages. The visitor pattern is a great example of this.

I think this may help;

Some of the patterns disappear -- that is, they are supported directly by language features, some patterns are simpler or have a different focus, and some are essentially unchanged.

[AIM-2002-005] Gregory T. Sullivan, Advanced Programming Language Features for Executable Design Patterns "Better Patterns Through Reflection

March 22, 2002

The Design Patterns book [GOF95] presents 24 time-tested patterns that consistently appear in well-designed software systems. Each pattern is presented with a description of the design problem the pattern addresses, as well as sample implementation code and design considerations. This paper explores how the patterns from the "Gang of Four'', or "GOF'' book, as it is often called, appear when similar problems are addressed using a dynamic, higher-order, object-oriented programming language. Some of the patterns disappear -- that is, they are supported directly by language features, some patterns are simpler or have a different focus, and some are essentially unchanged.

Related