lomeo: (лямбда)
Dmitry Antonyuk ([personal profile] lomeo) wrote2012-11-30 05:48 pm

Рекурсия

Я это как-то писал, но напишу ещё раз, бо тема поднялась.

Недостатки явной рекурсии по сравнению с комбинаторами (ага, zip3):

  • Рекурсия непонятна (согласен, это субъективное).
  • Обычно используется с декомпозицией, нарушая инкапусляцию.
  • Всегда используется для работы с элементами, вместо работы с коллекцией (wholemeal programming).
  • Цепочка вызовов проще для оптимизации.
  • Сложнее нежно мною любимый equational reasoning.

Юный хаскеллист, избегай явной рекурсии!

Ну и ссылочка, куда без неё!

[identity profile] nealar.livejournal.com 2012-11-30 01:56 pm (UTC)(link)
Когда сложность кода - уровня хелловорда, рекурсия понятна. А когда его становится побольше, уже надо спасаться комбинаторами.

[identity profile] lomeo.livejournal.com 2012-11-30 02:27 pm (UTC)(link)
Я стараюсь использовать её для реализации комбинаторов. Ну, т.е. вот есть модуль с объявленным типом, сначала, конечно typeclass morphism, потом более конкретные функции для этого типа. И вот всё это можно и через рекурсию. А наружу уходят чистые комбинаторы.

[identity profile] thedeemon.livejournal.com 2012-11-30 03:45 pm (UTC)(link)
>сначала, конечно typeclass morphism

Вот об этом было бы интересно подробнее послушать.

[identity profile] lomeo.livejournal.com 2012-11-30 03:58 pm (UTC)(link)
Да собственно тут (http://conal.net/papers/type-class-morphisms/) всё сказано.

Зачем нам алгебраические структуры в самом деле? Чтобы их использовать! :-)

Ну, и в нагрузку ещё немножко про дизайн (http://lukepalmer.wordpress.com/2008/07/18/semantic-design/) от Люка Палмера (правда, это оффтопик).

[identity profile] thedeemon.livejournal.com 2012-11-30 04:07 pm (UTC)(link)
Первое я видел, но хотелось бы примеров из личной практики.

[identity profile] lomeo.livejournal.com 2012-11-30 05:18 pm (UTC)(link)
Да ничего особенного. Абстракции как приём программирования :-)

Пишем же мы монады для ограничения контекста, для задания собственного подъязычка, мало ли для чего. При этом мы отслеживаем семантику, проверяем выполняются ли законы.

Так вот нужно не забывать реализовывать другие стандартные классы вместо того, чтобы рисовать собственные функции. Точно так же как с монадами: не забывая о семантике и законах.

ZipList, например. Структура та же, что и у списка, а семантика другая. Она отражена в реализации instance Applicative. Однако он неполноценный — это просто представление (view) списка. Если мы захотим работать с ним, как и с нормальным типом, добавить свёртку, например, то нам придётся это реализовывать. Так вот я стараюсь сразу делать это в Foldable, к примеру.

Ну и со всеми типами так. Пишешь монаду для работы с БД, например, или с пользовательскими сессиями, не забудь реализовать Functor, Applicative, если надо MonadPlus. Код получается более generic.

Напишешь какую-то функцию, смотришь, а это <|> из Alternative. Ну и чего сразу этот класс не реализовать и получить бесплатно другие функции с проверенными свойствами. Если твой код удовлетворяет законам класса, разумеется.

Как-то так. Несложное правило, позволяющее не писать кучу кода и рассуждать одинаково в кажущихся различными ситуациях.

[identity profile] thedeemon.livejournal.com 2012-11-30 05:42 pm (UTC)(link)
спасибо!

[identity profile] nivanych.livejournal.com 2012-12-01 07:09 am (UTC)(link)
> Зачем нам алгебраические структуры в самом деле?

Так, или с пользой? (c)