“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 are able to 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. OO-world children think interfaces at best - it’s close, but “not quite right” and the more attentive you become, the more it turns into “not at all”. And function signatures also know how to talk.

    To be honest, 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 GoF’s epoch-making work at least once; Probably, even non-sharpeners know that there is such a pattern - the iterator. And certainly everyone uses it every day. So (holding on to conditional C #):

    boolMoveNext();
    TCurrent { get; }
    

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

    MoveNext :: () -> BoolCurrent :: () -> 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 is no problem 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
    Кто в теме, тот, конечно, знает, что пример с IEnumerator <-> IObserver не нов.
    Удивляет, что редко кто осведомлен о том, что это далеко не единственный пример (правда, надо отдать должное, конкретно этот — очень яркий).

    Любопытные могут взять оставшиеся паттерны GoF и посмотреть на их «дуалов». Нередко будут получаться полнейшие бессмыслицы — это нормально: сама по себе «дуальность» выше земного мира и не считает себя обязанной считаться с практической пользой: но ведь и Солнцу, чтобы светить, от людей ничего не надо.

    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 to simply 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?

    Also popular now: