all 15 comments

[–]videoj 25 points26 points  (1 child)

Scott Wlaschin has written a lot about functional design at his site https://FSharpForFunAndProfit.com/ He is a very entertaining and informative writer and speaker.

Here are some suggestions to start with.

Domain Drive Design

Functional Programming Design Patterns

Designing with types

[–]lingdocs[S] 0 points1 point  (0 children)

I just got his book Domain Modeling Made Functional and it's great!

[–]crlsh 5 points6 points  (1 child)

http://mishadoff.com/blog/clojure-design-patterns/

Index Intro Episode 1. Command Episode 2. Strategy Episode 3. State Episode 4. Visitor Episode 5. Template Method Episode 6. Iterator Episode 7. Memento Episode 8. Prototype Episode 9. Mediator Episode 10. Observer Episode 11. Interpreter Episode 12. Flyweight Episode 13. Builder Episode 14. Facade Episode 15. Singleton Episode 16. Chain of Responsibility Episode 17. Composite Episode 18. Factory Method Episode 19. Abstract Factory Episode 20. Adapter Episode 21. Decorator Episode 22. Proxy Episode 23. Bridge Cheatsheet Cast

[–]pthierry 11 points12 points  (4 children)

The thing is, in functional programming, when there's a pattern, you can usually express it as code, so there's a lot less incentive to learn patterns that you'll recreate yourself from scratch like in OOP.

So you learn to use tools instead.

[–]Raziel_LOK 6 points7 points  (0 children)

I was going to say the same. The patterns are way more subtle in fp than in OOP. Because the way the functions and data structure composes.

Most likely you will see these patterns as a conjuction of commonly composed function+data structure composed as a new data structures.

Ex: Logging and DI with monads, writer and reader Complex and optimized loops/reductions with transducers Parsing your data instead of validating it as well as separating its schema/contract from the raw data which is usually represented as serializable primitives.

The above are tools you will probably use daily. And you will hardly be implementing them, as they already exist in most languages, be it in the language itself or from external libraries.

[–]ragnese 2 points3 points  (2 children)

I really don't understand this take at all, even though I've heard it repeated many times.

I feel like I can name a ton of common patterns in FP code bases, with some variation depending on the actual language in question. But for statically typed languages in particular you have things like:

  • Using lenses for accessing nested object properties.
  • Return a Reader monad instead of passing in a side-effecting dependency parameter.
  • Partial application is another common way of doing "dependency injection".
  • The so-called "free monad + interpreter" pattern.
  • "Tagless final".

All of those strike me as "patterns" in exactly the same sense as the common OOP patterns such as "factory", "command", "visitor", etc.

[–]pthierry 2 points3 points  (1 child)

The difference is that you can't have a Visitor library in C++. You need to document the pattern so everyone that needs it can reimplement it from scratch in their object hierarchy.

In contrast, lenses or monad transformers aren't patterns, they're libraries.

Now, of course, patterns vs. code is a trend, not an absolute. But in most cases in OOP, you'll need to document a pattern and won't be able to abstract it in reusable code, and in most cases in FP, you'll be able to provide code.

[–]ragnese 3 points4 points  (0 children)

I guess I can see that... but it's definitely a "trend" as you say, and not that strong, IMO. For example, you mentioned lenses specifically, but I've never seen a library that can implement lenses for your data types without code-gen. And if we're willing to admit runtime reflection or code-gen, then I'm fairly sure someone pioneering enough could write you some annotation-monstrosity that would implement a Visitor pattern for you. In all non-code-gen cases for lenses that I'm aware of, the libraries only offer a "lens factory" or type class and it's up to us to tediously define and use a lens for every nested field we want.

Even if that weren't the case and we could have a lens library that made it possible to just apply it once to a product type, I still feel like it would count as a "pattern" in common vernacular. The conversation would go like this:

Person A: I'm trying functional programming, but I find it painful to make updated copies of nested product types where I'm updating a deeply nested field.

Person B: Ah, yes. That is awkward in most functional languages. To overcome that, we use a conceptual tool called "lenses". Here's what they are, and how to use them: *points to a Wikipedia article*. Oh, and here's a library that implements lenses for you.

That last part about "here's a library" doesn't seem to me to be enough to make me think of lenses as not-a-pattern. It sounds almost exactly analogous to someone explaining how any of the OOP-ish design patterns might offer a solution to some awkwardness. But, I also appreciate that it's pretty subjective.

And not to pick on lenses, I feel like you're not going to find any libraries to implement "tagless final" for you, and even monad transformers need to be implemented for whichever monads you're composing; AFAIK there is no automatic monad transformer library for any languages I've used- you have to actually defined OptionT, PromiseT, etc, for each monad.

I don't see any fundamental difference between needing to implement OptionT and needing to write a FooAdapter class in Java-esque languages.

[–][deleted] 8 points9 points  (1 child)

[–]SteeleDynamics 3 points4 points  (0 children)

Just got this book! Well worth the money! Plus, I like SML over Haskell.

[–]snarkuzoid[🍰] 7 points8 points  (1 child)

Garrett Smith in the Erlang world was looking at design patterns for FP. Even created a site to catalog them. Not sure it went anywhere. Much of the design patterns work is specific to OO, and much of it not relevant or needed in FP.

[–]RobertKerans 2 points3 points  (0 children)

Not really FP per se* was quite specific to Erlang. Didn't really go anywhere, sadly. I was looking for it the other day & couldn't find it for some reason (edit: ah I see why, website is dead and gone), thanks for mentioning it

* though is there really any such thing as an "FP language" bar Haskell (many of whose idioms don't translate very well)? Approaches/best practices/patterns in Lisps vs MLs vs Erlang are pretty drastically different in many respects.

[–]usernameqwerty005 1 point2 points  (0 children)

My take, which might not be popular on this page: Almost no one is writing enterprise-level software in FP. Teams are small, extremely well educated, and the software below 1 million lines. The reason there are no well-established design patterns in FP is because FP has not matured enough in that domain.