Question

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?

Was it helpful?

Solution

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.

OTHER TIPS

I'm currently working on the book "Design and Architecture in Functional Programming". It describes many design patterns and approaches that are exist in pure FP world (primary language is Haskell), but not only. The book teaches you how to build big application from scratch with pure and impure state, multithreading, network, database, GUI, how to divide it into layers and obtain simplicity. It also shows how to model domains and languages, how to organize and describe architecture of the application how to test it, and even more.

The list of topics includes:

  • Approaches to architecture modeling using diagrams;
  • Requirements analysis;
  • Embedded DSL domain modeling;
  • External DSL design and implementation;
  • Monads as subsystems with effects;
  • Free monads as functional interfaces;
  • Arrowised eDSLs;
  • Inversion of Control using Free monadic eDSLs;
  • Software Transactional Memory;
  • Lenses;
  • State, Reader, Writer, RWS, ST monads;
  • Impure state: IORef, MVar, STM;
  • Multithreading and concurrent domain modeling;
  • GUI;
  • Applicability of mainstream techiques and approaches such as UML, SOLID, GRASP;
  • Interaction with impure subsystems.

The book is based on the Haskell projects I'm researching, especially a SCADA application Andromeda. The code for this book is available here. While the book is under development (it will be done till at the of 2017), I can recommend you to get familiar with my article "Design and Architecture in FP" here (Rus).

UPDATE

I shared my book online (first 5 chapters). See post on Reddit

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 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 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.

Hopefully not too tangential, but probably interesting for anyone browsing the answers to this question is this presentation Design Patterns in Dynamic Programming by Peter Norvig.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top