TGViewer
Лаборатория Математики и Программирования Сергея Бобровского Лаборатория Математики и Программирования Сергея Бобровского @lambda_brain · 1.41K subscribers
Post #2246 807
Пример, как работает мой агент. Вот я загнал в него ценный пейпер "Recursive Program Synthesis using Paramorphisms".

Как пишут рекурсию 98% программистов:

int SumPositiveNodes(Node node)
{
if (node == null) return 0;

int left = SumPositiveNodes(node.Left);
int right = SumPositiveNodes(node.Right);

int self = node.Value > 0 ? node.Value : 0;
return self + left + right;
}


Вот как напишут 2% ребят с хорошим университетским образованием (и кто вдумчиво решал мои доп.задачки на второй части АСД :) =>

int FoldTree(Node node, Func<Node, int, int, int> f, int seed)
{
if (node == null) return seed;
int left = FoldTree(node.Left, f, seed);
int right = FoldTree(node.Right, f, seed);
return f(node, left, right);
}

int SumPositiveNodes(Node root)
{
// чистая нерекурсивная логика
return FoldTree(root, (n, l, r) =>
{
int self = n.Value > 0 ? n.Value : 0;
return self + l + r;
}, 0);
}


Да, но это пока классический fold (катаморфизм), когда достаточно только одного результата.

Параморфизм требуется, когда в рекурсивной ветке нам нужно также иметь доступ к самой структуре (хвосту/поддереву).

ListNode DropLast(ListNode list)
{
if (list == null) return null;
if (list.Next == null) return null;

return new ListNode(list.Value, DropLast(list.Next));
}


=>

TOut Para<TOut>(ListNode list,
Func<int, ListNode, TOut, TOut> cons,
TOut nil)
{
if (list == null) return nil;
var rec = Para(list.Next, cons, nil);
return cons(list.Value, list.Next, rec);
}

ListNode DropLast(ListNode list)
{
return Para(list, (head, tail, rec) =>
{
if (tail == null) return null;
return new ListNode(head, rec);
}, null);
}


Результат: исходный код был краток и прозрачен для понимания, а нового кода стало существенно больше, и теперь нифига не понятно :)

Вот в чём сермяга: Para -- это универсальный рекурсивный каркас (порядок обхода и базовые случаи единообразны), который мы тестируем 1 раз.

Далее нам достаточно только проверять нерекурсивную логику внутри различных cons под этот паттерн в нашем проекте.

+ можем использовать Para как fold:

int SumPositive(ListNode list)
{
return Para(list, (head, tail, rec) =>
{
int self = head > 0 ? head : 0;
return self + rec;
}, 0);
}


Где это полезно? В работе со списками и деревьями, в обработке json и подобных структур, в ETL - сокращаем кучу рекурсивного кода (возможно, вообще до одного параморфизма), а добавлять новую логику можно императивно. Но это конечно уровень больше архитектурного code review.

К весне, надеюсь, кто у меня (пере)проходит тему АСД, бета-версия агента будет периодически делать такое ревью решений через клода4.6 и жпт5.3 (бесплатно).
  • 👍 37
  • ❤ 16
  • ✍ 3
More from @lambda_brain
  1. Oct 1, 2026Ребята спрашивают, ну ок, моё скромное мнение. у вас где-нибудь можно прочитать ваше мнени…
  2. Sep 30, 2026Ладно, вот вам база, почему так трудно переучиваться с императивного/объектного стиля коди…
  3. Sep 30, 2026Ну, с Днём Рунета! Многие годы Рунет был эталонным примером свободы, а сегодня превратился…
  4. Sep 28, 2026. Облако драгоценностей за неделю. Дипломный проект разросся уже так, что расширил его до…
  5. Sep 27, 2026GELU (Gaussian Error Linear Unit) -- базовая фича архитектуры трансформеров, да и вообще в…
  6. Sep 27, 2026Продолжение сериала "Совершенно не удивлён, и дальше будет только хуже" (с) На этой неделе…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →