📜 ⬆️ ⬇️

“My light is a mirror! - say, yes, show my dual ... ": design one good framework and get the second one as a gift

Stones of ancient temples can talk, but few listen to them. The universe is filled with sounds that we humans do not hear; colors that we don’t see: sometimes it’s about the objective limitations of the body and spirit, but there are also subjective reasons - lack of knowledge and skills or the inability to use them in everyday practice. A vivid example of the second in the world of programming is function signatures. At best, children of an OO world think in interfaces — this is close, but “not quite that,” and the more attentive you become, the more it turns into “not at all”. And function signatures also know how to talk.

Honestly, I would like to start from truly high-level abstractions, but my previous experience shows that even the simplest mathematical truths in non-mathematical language “do not sound”. Only incidentally I will note that everything that I am talking about is born of mathematical thought - and, accordingly, can be strictly formalized.
And now - specifics. Probably, all more or less “rummaging” have bothered to read the epoch-making work of GoF at least once; Probably, even the “non-aging” ones know that there is such a pattern - the iterator. And certainly everyone uses it every day. So (holding on to conditional C #):

bool MoveNext(); T Current { get; } 

... and now the same thing, but without syntactic noise (it is significant that in fact "without syntactic noise" means on Haskell'e):

 MoveNext :: () -> Bool Current :: () -> t 

... forgetting for a while about the types and focusing on the arrow itself (->), one involuntarily comes to the question of what will happen if it is “reversed”? Then it will turn out:

 MoveNext' :: Bool -> () Current' :: t -> () 

A slight sensation of disharmony, yes? If there are no problems with t -> () , then Bool -> () looks more than suspicious. And really - this flag was used to signal the end of the sequence, right? In the inverted form, the case of True -> () has no useful meaning - only False -> () is sufficient. The binary uncertainty that the Bool type provides is lost - and therefore it should look like this:

 completed :: () -> () next :: t -> () 

Nothing like? How about reactive extensions ?
Wow! The signature (well, more precisely, signatures, but the approach itself works on an individual level) the functions of one (almost) classy (mini) framework told us about another not less steep one, yes? You just need to be attentive and hear.

Good news to the world from category theory
Who in the subject, of course, knows that the example with IEnumerator <-> IObserver is not new.
It is surprising that rarely anyone is aware that this is not the only example (although we must pay tribute, specifically this one is very bright).

Curious can take the remaining GoF patterns and look at their duals. Quite often, sheer nonsense will be obtained - this is normal: the “duality” itself is higher than the earthly world and does not consider itself obliged to reckon with practical benefits: but then the Sun does not need anything from people to shine.

Why, then, "almost cool"? Yes, because of the disharmony, which entailed the need for additional grinding and polishing. Strictly speaking, turning the arrows back, it turned out something not quite useful, which can be interpreted as a disadvantage of the original signature. Looking ahead, I can say that this very signature can be redefined in such a way that disharmony disappears and it will be enough just to turn to its dual. But I won't bother with this ... at least not in this note.

Better to sum up, based entirely on my experience:

  1. Function signatures can talk, but programmers often remain deaf.
  2. Every time you meet a well-designed function, ask yourself what its dual is and if it could be useful for any tasks.
  3. If a dual exists, but requires a “light modification” as in the example above, then most likely the original signature has some implicit defects; maybe it makes sense to redefine it so that there is no such problem?

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