📜 ⬆️ ⬇️

Talking to FPConf speakers

Hello!

The FPConf conference is already this Saturday, we are already 160 and it is not too late to drop into the last car. Registration is here .

And the day before we decided to ask our speakers one rather ambiguous question. We publish the answers, your options are welcome in the comments!
')
image

In object-oriented languages, there is a well-known list of design patterns from Gang of Four. There is no such list in the functional languages. From your point of view, why so?
Such patterns are not needed when programming in functional languages ​​or just their canonical list has not yet developed?



Anton Kholomiev, Haskell
For Haskell, there is such a list, but it is called differently and there are other patterns,
in the style of OP. Here


Sergey Lobin, Scala
In my opinion, patterns are the principles of FP, which can be used as cubes, collecting beautiful programs :)


Sergey Tikhon, F #
In the issue of patterns for a programming language, I agree with Peter Norvig who said that "Design patterns." Most of the problems that solved the classical patterns from Gang of Four have already been solved in functional languages ​​in one form or another. “Functional patterns \ abstractions” are and will appear (for example, Monads), as a set of common approaches for managing the complexity of developed applications. Perhaps over time, there will be one general list that we all recognize as canonical, but this will be caused by a noticeable increase in the complexity of the tasks that will allow solving functional languages.


Alexander Granin, Haskell
The question is very correlated with the topic of my report. And I raised it several times at our meetings LambdaNsk.

Design patterns in OOP are artificial constructs that solve a particular technical problem that cannot be solved in a natural way — by the syntax of the language, top-level idioms or concepts. A significant part of the patterns (if not all) operate on OOP concepts such as "inheritance", "polymorphism", "abstraction", while neither these concepts, nor any other specific syntactic construction of OOP language, solve the problem directly. At the same time, in functional languages, these patterns either degenerate (Visitor), or simply become unnecessary (Command) - in view of the fact that there are concepts in the FI itself that can directly solve the problem: FVP, lambda, pattern matching, first-class functions, immunity, composition, laziness and much more. For example, Visitor is easily replaced by pattern matching and FVP, while Command is simply replaced by first-class features. In OOP, patterns are complex constructs that are not inherent in the OOP language itself. That is, to solve a problem, OOP-language and its elements are not enough: you need to make one or another mechanism out of these elements. And many similar mechanisms in the end and are summarized in OOP-patterns. On the contrary, in order to solve a problem in FP, only language constructs are sufficient, and it is often enough just to compose the type of function. If there is a type, the implementation of the function will be simple.

At the same time, the FP has its own “patterns”, although I prefer to call them “idioms”. You heard about them: different monads, comonads, functors, arrows, applicative functors, combinators, transducers. In addition, in the OP there are such patterns as FRP, STM, lenses. What, in my opinion, is the difference between OOP patterns and FP idioms?

The OOP pattern is a solution to the problem “from the outside” with an imperative approach. The OOP pattern addresses entities and their mutable interaction. The OOP pattern describes how the system works. There are OOP patterns that are needed to only realize the functional idiom missing in the language (Visitor is a comparison with a sample and FIB).

OP-idiom is a solution to the problem “from the inside” by a functional-declarative approach. OP-idiom addresses to properties and their un-mutable transformation; The OP-idiom describes “what is” the essence, what are its inseparable properties.

What properties are we talking about? For example, if you have a functional list, then it is initially, even without your knowledge of it, a monad. And if you have the game "Life", then its cellular field is already a komonad. From this it follows, by the way, that the FP programmer does not simply construct a solution to the problem, he searches for hidden characteristics and properties in the subject area, and already proceeding from this knowledge, he solves the problem by applying this or that FP idiom. Such code — built on properties and transformation — will be idiomatic functional code.

But the topic of design of large applications in functional languages, of course, is still poorly understood - in view of the low prevalence of these very languages. Accordingly, there is little literature. I am going to raise this important issue in my report.

Related Links
* Does OP replace GOF patterns?
* Design Patterns in Haskell
* Design patterns in OP
* Idiomatic functional code (presentation from my performance on LambdaNsk)
* Idioms in Haskell and OP: 1 and 2

Denis Redozubov, Haskell
+1 to the previous answer.


Nikolay Ryzhikov, Clojure
Not all GOF patterns are the same. Some are too low-level - for example, Iterator. The FP has its own (more expressive) arsenal for similar tasks: map, reduce / fold, walker. As well as a number of highly functional low-level patterns: monads, zippers, transducers.

However, a significant part of the templates are high-level constructions that are useful and understandable to experienced programmers, allowing you to structure and describe the program in the large. And they may well be used in the OP, sometimes with a slightly different implementation from the original.

For example, Chain of Responsibility can be expressed through HOF as the decoration of functions (use js for accessibility :):

function handler1(next_handler) { return function(args){ if (exp){ // some logic next_handler(args); //pipe to next handler } else { return some_responce; //intercept } } } var stack = handler1(handler2(handler3)) // build chain (stack) stack(args); // process chain 


Therefore, I think you just need to re-release Design Patterns for AF. Perhaps you are the one who will write this book :)


Nikita Prokopov, Clojure
There are patterns both there and there. OOP language tells you: there are objects, do what you want. Freedom, but unconstructive. The pattern is “if you construct an object according to such a scheme, it can be used for such and such purposes”. Concretization

Therefore, I would not go so far as to attribute some special properties to the FP languages ​​that invalidate the patterns. A pattern is simply a classifier of frequently encountered "code forms." Specific OOP patterns from GoF are not needed because there are no objects. But FP patterns are needed. Somehow, after all, the OP code is written, and it is not that each person is unique.

Well, there is no well-known list, because no one has compiled it yet. Informally, it is, just transmitted implicitly. Plus, it will most likely be very different for different languages, at least for typed FP and for untyped.

I would suggest that for typed need for patterns is higher, because they need recipes for how to "wrap" types in order to get around a particular problem. Such recipes very quickly become non-trivial, and it is more and more difficult to reach them with your mind. So from an educational point of view, “patterns of typed FP” are very much in demand.


Mikhail Limansky, Scala
Functionals do not need patterns, because we are creative people, not artisans.

But seriously, in OOP, patterns are generated by the complexity of the object model itself. All you have is encapsulation, inheritance and polymorphism, but there is no sense in the language of how to use it. Those. knowledge of the language and the basic principles of the PLO is not enough to avoid shooting off one's leg, and not to turn the code into an insane mess. This is what patterns are needed for (well, when patterns did not help, treatises on refactoring come to the rescue).

In the OP, on the contrary, we go from behavior - from type classes that are already part of the language. It turns out a certain Unix way for programming - a small class performs one small task and does it well.


Arseny Zhizhelev, Scala
The gang of four "staked out" the list of patterns that existed at the time, and seemed universal and widely applicable. Over time, new patterns appeared, and flaws in the old ones (for example, dependency injection replaced the factory).

As already mentioned above, functional languages ​​also have sets of good practices, only none of the sets have yet become well-known and popular. This opens up the possibility of including in such a list new approaches and libraries implementing them. One of the interesting ways to use functional languages ​​will be discussed in my talk about the SynapseGrid library, which implements the Functional Reactive Programming approach on Scala.

UPD. In the morning we received a response from Edward and decided to publish it in a separate post.

Updates from the rest of the participants and speakers of the conference - in the comments. See you at FPConf!

Source: https://habr.com/ru/post/264695/


All Articles