Functional Design and Architecture is released (+DotD 45% discount on paper and e-book)

Hi folks,

There is a good reason for me to announce my advanced FP/Haskell engineering book here today. Functional Design and Architecture was recently released at Manning Publications, and today it is in the Deal of the Day promotion program with a 45% discount for both print and e-book:

Print: $̶5̶9̶.̶9̶9̶ $32.99
E-book: $̶4̶7̶.̶9̶9̶ $26.39

A long and dramatic writing story is now finished - 8 years in the making, if we consider its early self-published LeanPub edition and 4 years for Manning’s edition alone.

The book is unique, most wanted, and needed in the functional world. Remember Taylor Fausak’s surveys? Year to year, these three topics were always at the top of what Haskellers wanted to read about:

Which Haskell topics would you like to see more written about?

  • Best practices
  • Design patterns
  • Application architectures

My book explicitly discusses functional idioms, functional design patterns, functional application architectures, and best practices. While some may argue that they have a different set of best practices, where is another comprehensive and systematic source of knowledge on this? My book is unique, especially considering it proposes a practical methodology for building applications: Functional Declarative Design (FDD), a counterpart to Object-Oriented Design. The book is insightful, deep, and pragmatic; it brings bright FP ideas into action and rethinks various mainstream approaches in the functional setting. A much-needed gap between the two worlds.

I hope the book will become another software engineering classic. At least some readers say it has all the chances for this. I believe the book deserves to stay near other great books from great authors: Domain Modeling Made Functional by Scott Wlaschin and Functional and Reactive Domain Modeling by Debasish Ghosh. These two, and Vitaly Bragilevsky, the author of excellent Haskell in Depth, kindly endorse my book, which is an honor.

This is a unique book that fills a previously empty slot in the field of software development within the functional programming approach. As the author of “Haskell in Depth,” which focuses primarily on the Haskell language itself, I enjoyed reading about developing Haskell applications from an orthogonal perspective: the perspective of software design and architecture.

Vitaly Bragilevsky, JetBrains, author of Haskell in Depth (Manning)

The real value of the book is that it discusses the goodness of advanced functional programming patterns in the context of real world business applications. There are books which discuss concepts like free monads and applicative with toy examples. But Functional Design and Architecture explains the free monad pattern in the context of designing business centric EDSLs and how it can lead to a clean separation of the declarations and implementations in designing domain models.

Debasish Ghosh, Conviva, author of Functional and Reactive Domain Modeling and DSL in Action (Manning)

This book covers all aspects of “big picture” software design from a functional programming viewpoint, and powerfully demonstrates that functional programming techniques are not just academic but can be applied to any business domain. It is comprehensive, covering classic domain-driven design, but also how to work with stateful, reactive and concurrent applications.

Scott Wlaschin, author of Domain Modeling Made Functional (Pragmatic Bookshelf)

I’m getting great reviews of the book. People love it!

I’ve finally got the time to read Functional Design and Architecture by Alexander Granin. It’s a great book, full of insights about how to use DDD in Haskell and how to design a great application. I still prefer Kotlin, but if you like Haskell, this is probably the best book!

Uberto Barbini, author of From Objects to Functions

A month later, what was started as a simple excursion into eDSLs, has led me into the storage depths of functional interfaces, applicative functors, combinatorial models, and free monads. No life forms detected. If I don’t recover, blame Alexander Granin for my demise.

Tyrone Dunn

I’ve been following its evolution through its MEAP iterations. An excellent and unique read!

Guido Mureddu

There are other great reviews, and I’m grateful to all folks who helped me to write this book, including to those Patrons and early readers who were with me when I first started writing the early edition in 2016.

I’m currently on the finishing line with my other book, Pragmatic Type-Level Design. I aim to release it by the end of the year. This one is more Haskell-oriented than FDaA, but still, my goal is to fill various gaps in software engineering, especially in functional programming. PTLD describes reasonable, pragmatic approaches to type-level programming in Haskell and similar languages and provides even more software design tools not presented in FDaA. These two books finely complement each other.

PTLD is nearly finished; all eight planned chapters have been written, and all five appendixes have been completed. I’m working on the last part, Rosetta Stone, which sheds light on how to apply the ideas in other languages. There are four more possible chapters to write because type-level programming in Haskell is a broad topic. If I see a significant interest (1000+ purchases on LeanPub), I’ll consider expanding the book beyond that. As for now, it has 330 pages and will gain 70 more. Consider supporting my work because writing advanced and unique books is a super expensive and extremely difficult endeavor.

13 Likes

I received my copy recently! Can’t wait to delve into it

1 Like

That’s great, thank you!

Do any of these books expand on the ‘Blub paradox’ that @jaror mentioned? I haven’t seen a Haskell book on Backpack yet.

Both my books pay central attention to demystifying interfaces in functional languages. As the discussions with Haskell people have shown, this notion and its importance are not clear to many, and there are too many myths about this topic.

In FDaA, I talk about various interface-like abstractions, free monads included, and mention even more. The whole Functional Declarative Design methodology would not be possible without free monad interfaces. Why not type classes? Again, type classes are not interface-like abstractions; they are genericity-like abstractions, although they can be used as interfaces to some extent. They lack many important properties of a true interface-like abstraction, and do not solve specific problems of software design.

In PTLD, I touch on this topic once again in a couple of dedicated sections:

6.2 Two functional interfaces
6.2.1 Properties of a true interfacing mechanism
6.2.1 Type class versus Free monad
6.2.1 Free monad interface
6.2.1 Type class interface and the Dynamic Payload design pattern

I don’t talk about Backpack in my books. It is a side feature that is marginal enough even in Haskell. My books are not intended to shed light on marginal Haskell features because in general, my books are not about Haskell or functional programming. (But I must admit, PTLD is much more about advanced Haskell than FDaA is.)

However, from what I see and know, the Backpack module system is most similar to OCaml’s module system and can be discussed from this perspective. OCaml’s modules are both interface-like abstractions, and genericity-like abstractions depending on the usage perspective. It seems learning OCaml’s modules can help with Backpack.

Both my books pay central attention to demystifying interfaces in functional languages. As the discussions with Haskell people have shown, this notion and its importance are not clear to many, and there are too many myths about this topic.

And yet all the Haskellers associated with the sponsors listed here:

https://haskell.foundation/donations

along with the Haskellers here:

seem to have been doing rather nicely, despite this alleged lack of clarity regarding the notion of the interface and its importance in programming (functional or otherwise)…

2 Likes

If you want to say, “People do it just fine, your knowledge is not needed,” then I don’t see this as a valid argument.

1 Like

what’s weird to me about the “Typeclasses vs Interfaces” thread is that I don’t even see code like that from OOP/OOP-like/imperative languages much anymore. it’s all “plain functions, plain data, avoid abstract classes like the plague, and use interfaces/traits/type classes sparingly”. what you’ve termed “interfaces” is what no one wants to be stuck maintaining any longer.

I must be missing something vital because I can’t make heads or tails of what problem this free monad approach is supposed to be solving. if your domain naturally breaks down into a DSL, great, go for it. but if it doesn’t, don’t force it.

as an example, I built an operational tool a few years back that needed to keep track of the operations that needed to be performed on infrastructure and it couldn’t rely on having that state in memory. a finite state machine was obviously the right thing to do here but I built an eDSL to express those operations on top of it. it was a mistake. I had the domain ever-so-slightly wrong and the DSL couldn’t handle the change to the mode of operation. so we had to rewrite the entire application to remove the eDSL after attempts to fix it went sideways. when we did, there was no eDSL, but the finite state machine remained – because ultimately, deriving the current state of the world, the change that needs to be applied, and performing that operation was what was critical.

so I’ve been a bit skeptical of DSL/free functor approaches since then. they rely on knowing the domain in a way that you just can’t guarantee. but more direct code expressed as functions over plain data is more flexible. when I reach for a type class, it’s because I want dynamic dispatch at the use site, not encapsulation.

just my two cents. I’m sure others have different experiences. just feel like this particular recommendation is put forward without the necessary caveats about its drawbacks – a point I encountered the hard way. it’s a very frequent recommendation in the Haskell community (or at least it was 5-10 years ago) and at least at the time, I didn’t have enough experience to totally grasp when the technique was applicable and it was not, and that eventually bit me.

7 Likes

This is essentially a false premise. I see this everywhere. From my big experience, I’ve seen more than enough of this to say that it’s a perfectly viable practice. Shall we proceed to projects on GitHub?

Avoiding the mechanism of interfaces in C# and Java or traits in Rust is not a common practice. But when it’s a practice, and I’ve seen enough of this, too. And quite often, the code was just naive and suboptimal from various perspectives and was barely working and hard to maintain.

it was a mistake.
so we had to rewrite the entire application to remove the eDSL

So you designed an eDSL, it was bad, you removed this, and now you’re essentially saying the whole concept is a lie. But if you read my book, you could learn that “everything is an eDSL, whether you know about this or not”. Every structured code that has a certain idea is an eDSL.

if your domain naturally breaks down into a DSL, great, go for it. but if it doesn’t, don’t force it.

This is not a technical argument because it is not possible to measure. Every domain can break down to many various DSLs having vastly different designs. Depending on the design and purpose, DSL can be a good or bad fit. This is always situational and should be decided case-by-case.

they rely on knowing the domain in a way that you just can’t guarantee

No, it’s some designs of DSL that may have this unfortunate property. Other designs may be more flexible and appropriate.

just feel like this particular recommendation

I’m not sure, what recommendation? My book is much wider than that. I mean, MUCH wider.

1 Like

I had typed up a longer response but I realized something rereading your reply.

But if you read my book, you could learn that “everything is an eDSL, whether you know about this or not”. Every structured code that has a certain idea is an eDSL.

I’d considered reading your book. I was actually thinking about buying it until I got this response:

So you designed an eDSL, it was bad, you removed this, and now you’re essentially saying the whole concept is a lie. But if you read my book, you could learn that “everything is an eDSL, whether you know about this or not”. Every structured code that has a certain idea is an eDSL.

has convinced me not to. in the future I recommend not writing paragraphs like this one.

ok, you’re smarter than I am. anything else? ultimately it’s us mere mortals that have to reap the consequences of any particular design philosophy. I’m not interested in this particular measuring contest, especially if it’s going to get technical.

4 Likes

The user you are replying to brought their experience, and concludes with “just my two cents. I’m sure others have different experiences.”
I wish your luck with the book sales, you are not doing yourself any favour.

Is there any Haskell codebase — open source, that is — that follows the patterns laid out in your book? I confess many of the terms in the index are new or not clear to me (starting with “interfaces”) and would like to see how different the code is from Haskell I am used to.

8 Likes

I confess many of the terms in the index are new or not clear to me (starting with “interfaces”) and would like to see how different the code is from Haskell I am used to.

Numerous code bases use patterns from my book. Some are commercial, and most are showcases. Commercial code bases are mostly private; done by me and other folks who then informed me they follow the methodology from the FDaA book.

What I’m writing about is more applicable to big IO-bound code bases, especially those with an extensibility requirement, and those that many teams should work on collaboratively. The approaches may not be as praised in CPU-bound applications and in specific niches with practices already set (for example, in compilers).

In big code bases of business applications, the concepts I’m writing about are essential. Interface-like abstractions are necessary for decoupling parts and making the code more maintainable. Complexity should be controlled. Some design patterns may do good stuff. Interface-like abstractions, be it free monads, Service Handle, ‘interface’ from Java/C#, or something else, are unavoidable in complex code bases unless we’re practicing spaghetti programming. This is why I invented my methodology, Functional Declarative Design, and have proven it works - in Haskell and everywhere. It is certainly based on Hierarchical Free Monads as the most powerful functional interfaces (and a counterpart to OOP interfaces) but is not limited by them. It also allows to follow various design principles I state in the books, including SOLID, Low Coupling, High Cohesion, Divide and Conquer, No Perfectionism, Pragmatism, Dumb but Uniform, and others. In my projects, I compare different approaches and talk about the implications of various designs in terms of simplicity, accidental complexity, proper structure, and testability of the architectures.

First of all, there are repos with code from the books:

Functional Design and Architecture repo
Pragmatic Type-Level Design repo

For Functional Design and Architecture, I created two showcase projects: Andromeda (spaceship control software) and Hydra (a full-fledged multithreaded application framework). I accompanied the framework with a number of demo applications shipped with it. Unlike various effect system libraries that almost completely lack examples, I want my users to have examples of usage and best practices provided out of the box.

Andromeda. It is a complicated platform for spaceship control software. There was no goal to create real software, so it is incomplete yet representative. There are free monadic and GADT-based eDSLs for defining spaceship hardware, control networks, and control scripts. For example, HDL language. Here is the usage. Later on, this domain model becomes a simulated actor-based model operated by the simulator. The MVar Request-Response design pattern is used to organize the communication between the actors.

Hydra, a full-fledged concurrent application framework for HTTP services and console apps. Initially developed for the book, it works and can, in principle, be used in production. You’ll find these design patterns in there: Typed-Untyped, Typed Avatar, and also, Hierarchical Free Monads architectural pattern. Although people may call it “effect system,” I don’t call it so because I follow the mainstream terminology. My languages are subsystems expressed by free monadic interfaces, similar to IoC frameworks in the mainstream world. The framework supports these subsystems out of the box: logging, relational DBs (with Beam integrated the way this reduces its complexity), STM-like state, both untyped and fully typed key-value DB support (Redis and RocksDB), Process (for thread-safe multithreaded apps), and others.

What’s important is that it’s not just one framework, it’s 3 of them having different implementations:

Hydra is shipped with various demo applications including those that allow to measure and compare the performance of the engines.

Operations cnt FT FreeM ChurchM IO
10 0.265 0.222 0.223 0.227
100 0.221 0.226 0.228 0.222
1000 0.227 0.245 0.223 0.226
10000 0.229 4.106 0.227 0.224
100000 0.289 inf 0.31 0.309
1000000 0.859 inf 1.134 0.857
10000000 6.384 inf 9.507 6.413
20000000 13.734 inf 18.997 12.588
30000000 18.16 inf 28.568 17.76

Besides, there are commercial products based on my ideas. They may not be fully representative because in the real world, nothing is pure and book-like, but they exist nevertheless.

Additionally, I created various side projects to test my ideas in different ways.

For Pragmatic Type-Level Design, I created many other showcase projects to demonstrate the ideas.

This is not an exhaustive list of projects and ideas from my books. I also can compose a huge list of additional materials: posts, articles, talks and slides I made to teach those novel concepts. As I said, my books are comprehensive, advanced and pioneering, and this only list shows how much thought and effort was made.

4 Likes

Alright, given that collection of prior work (and your comments regarding OCaml) - do you consider Standard ML’s notions of modularity to be closer to “the ideal interface” than Haskell’s?

Well, if we put this on a comparison axis, then I find OCaml’s module system to be a better interfacing mechanism than Haskell’s type classes. Free monads, or, at least interpretable languages, are better in Haskell. Type classes are the best when creating libraries and abstract algorithms because they are closer to math expressions; otherwise, type classes are rigid and not values. However, I would not choose interpretable languages or free monads in OCaml without real need. These work better in Haskell.

In general, the concept of interface-like abstraction is not something magical, and is not something to despise. I don’t agree that interfaces have a “sparse” usage or no one wants to deal with them in the mainstream languages, like they are a a side and harmful tool. Quite contrary, they are the primary tool to beat complexity, to structure the layers and subsystems (see Domain Driven Design) and achieve so.e extensibility. They may not occur on every step in the code bases, but they are central and most important architecture-related tools.

@atravers And also, maybe, you have something else in your mind, not OCaml modules? I’m not quite sure I know what Standard ML has for modularity

I’m not quite sure I know what Standard ML has for modularity

Functors (parameterised modules) - see section 5 (page 34) of The History of Standard ML.

It’s difficult to judge from the reference you provided. They look close to what OCaml has. But I can’t say definitely without trying and using.

I would say, we’ve stepped on the ground of theoretizing as this often happens in such discussions. I want people to understand: these talks what is better and what is not, while there is no practice and understanding of why these tools exist and what design problems sove, these discussions will not be insightful. One needs to hit the issues of bad code design in the absence of interfaces, and mindfully understand what is wrong. This needs some conscious thought process; otherwise it will be “this is fine” with no progress in understanding.

I can say for myself; I started seeing the need and value of these concepts when found myself trapped in the code I couldn’t comprehend and advance. I was self-aware enough to stop and realize the problem. This was the moment of enlightment. Many people, not only Haskell people, do not have this self-awareness to stop and ask the right questions. The result is messy code bases. (BTW, all the repos I’ve seen and dealt with in Cardano were such - mess, spaghetti and lack of structure; not only because they lacked interfaces, but also because there was no separation of layers and abstraction levels).

Then this might also interest you:

where the author makes observations regarding modularity as provided by Haskell and Standard ML. But the choices the author makes regarding type systems is also notable.

1 Like

I think everyone has had the chance to make their points. It might be time for the mods to consider locking this thread.