Re[5]: Мастер-класс по ФП
От: D. Mon Великобритания http://thedeemon.livejournal.com
Дата: 04.01.09 15:12
Оценка:
Здравствуйте, geniepro, Вы писали:

G>В F# конвейерный оператор обозначается как |>

G>Насчёи Окамля не знаю, не нашёл такого оператора в описании...

В Окамле он не входит в язык или стандартную библиотеку, но чаще всего тоже обозначается |> и описывается отдельно: let (|>) x f = f x;;
Re[12]: Мастер-класс по ФП
От: BulatZiganshin  
Дата: 04.01.09 15:13
Оценка:
Здравствуйте, NotGonnaGetUs, Вы писали:

dmz>>
dmz>>process (inp filt group_by consume) = inp >>> filter filt >>> group group_by >>> consume
dmz>>


dmz>>В этом конвейре можно настроить все — и поведение, и данные. И даже сделать так, что бы конкретное поведение определялось структурой данных на входе.


NGG>Целиком и полностью согласен и нисколько с этим не спорю. Я только повторяю заезженную истину о том, что дьявол в деталях.

NGG>Как делается настройка "и поведения, и данных"?

передачей их в качестве параметров

NGG>Как повторно использовать "труды" настройки?


видимо, речь идёт о partial application?

NGG>А если я напишу класс

NGG>сlass TaskNumberOne {
NGG>void process(Source inp, Filter filt , Group group_by, Consumer consume) {...}
NGG>}
NGG>вставив внутрь строчки для органиции потока данных по этой цепочке, я тоже разом решу все возможные проблемы?

да, а разве нет? разница только в том, что на C# это наверно будет достаточно сложная функция

NGG>Ну, так я и прошу озвучить в чём же этот подход заключается, как при его использовании решаются проблемы борьбы со сложностью озвученные в тех же самых шаблонах грасп и т.п. Так же мне интересно, что мешает применять этот "другой" подход, скажем, лабая код на java. Станет ли он сразу не эффективным и почему? Если не станет, то в чём его плюсы перед имеющимся в наличии ООД? Если плюсы есть, то я стану использовать его в повседневной работе и буду рад безмерно.


все три C* языка активно добавляют в свой арсенал ФП фичи. поэтому давайте посмотрим скажем какие проблемы возникнут при использовании ФП подхода в чистом С или C++ 80-х годов:

1) нам нужна передача функций в качестве параметров и возвращение их в качестве результатов. это поддерживается
2) нужна поддержка анонимных лямбд. этого нет — все функции должны быть описаны глобально. но по крайней мере выразительную мощь языка это не изменяет
3) нужна поддержка частичного применения. этого нет
4) нужен двухсторонний автовывод типов с автоматическим обобщением. этого тоже нет, что затрудняет разбиение алгоритмов на множество небольших [глобальных, локальных и анонимных] функций — засребёшься описывать типы всех их параметров и результатов
5) нужно ленивое вычисление. тоже нет
6) ну и самом собой, нужен GC

в остальном ФП подходы вполне применимы и на C* языках

dmz>>В данном топике задачи слишком простые, что бы к ним серьезно применять термин "дизайн". Problem K — уже гораздо интереснее.

NGG>Согласен полностью. Простые. Но я же смог показать на простой задаче применение ОО-дизайна. Так же точно, мне думается, не должно быть проблемой продемонстрировать "другой подход к дизайну" на этой же задаче. Некоторые примеры были показаны, я сравнил решения, задал волнующие меня вопросы. Ответы на подобные вопросы по своему решению я могу дать, по чужим — хочу услышать.

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

вот пример. представим классическую gui-библиотеку. реализация диалога настроек на ней может выглядеть так:
1) создаём все необходимые controls
2) заполняем их исходными данными
3) отображаем диалог
4) после нажатия Ok обновляем переменные

удобно ли это? на мой взгляд нет — нужно сгруппировать описание контрола, перевод данных в него и обратно. соответственно ФП-дизайн здесь состоит в создании высокоуровневых контролов, которые несут в себе не только свои данные, но и ассоциированные с ними действия. и тогда программа будет выглядеть так:
runDialog [
  Editbox [Color := Red, Label := "Speed", Init := (do setText =<< readVar speed), 
                                           OnOK := (do getText >>= writeVar speed)]
  SpinButton ....
]
Люди, я люблю вас! Будьте бдительны!!!
Re[14]: Мастер-класс по ФП
От: dmz Россия  
Дата: 04.01.09 15:22
Оценка: +1
Здравствуйте, yumi, Вы писали:

Y>Здравствуйте, dmz, Вы писали:


dmz>>Более того, человек, который написал мега-фреймворк для сортировки ящиков, может уже не работать на момент, когда изменения понадобятся. Придет следующий человек. Получит задачу сделать так, что бы помимо ящиков, сортировались так же и бочки. Увидит фреймворк. Как думаете, он будет вникать в весь "повторно использованный код" ? Или проведет "рефакторинг" — т.е. выкинет или забьет, и напишет свое?


Y>Вы не так поняли, точнее смотрите с другой точки зрения. Только с позиции одного разработчика. Фича мега-фреймворка как раз в том, что какую-то часть, например, сортировку ящиков может делать один человек, а другой может писать сортировку бочек. Причем им нужен только интерфейс ISort.


Тема сортировки пока никем не поднималась, но в рамках предметной области допущение, что она понадобится — вполне резонное. ISort — это, кстати, у кого будет такой интерфейс? В рамках предложенной декомпозиции? Ась?

Но смотрю я не с точки зрения разработчика. Смотрю я, допустим, с точки зрения заказчика или аутсорс-менеджера. И вижу, что вместо задачи построения дискового индекса, которую я заказывал, мне впаривают фреймворк для (цитирую)

[quote]
Дано: источник данных, критерий разбиения данных на группы
Надо: данные разбить на группы, обработать данные в группах.
[/quote]

Таких задач не бывает, но да ладно. Для увеличения вероятности того, что нам такая задача понадобится — расширим ее аудиторию с рамок данного проекта до всего мира. Выложим в сеть. Как будете искать ее решение в гугле? Ладно, допустим, мы нашли.

Что мы видим? Для того, что бы данным решением воспользоваться — нужно пользоваться контейнерным (по сути) классом Group (если у нас данные ходят в каком-нибудь обычном List — придется написать адаптер, какой — нибудь свой FromListProcessor, разобраться, чем отличаются Group от Processor с одинаковым интерфейсом (две разные сущности с внешне одинаковым поведением, тесно сцепленные), а потом еще вытащить свои данные из Group.

И это вместо того, что бы тупо в лоб воспользоваться фундаментальными примитивами group, map, filter — которые будут работать с любыми списками (не знаю, как в джаве, но в питоне есть group, filter, map прямо вот в таком виде) — на которые данная задача естественно декомпозируется.
Re[6]: Мастер-класс по ФП
От: FR  
Дата: 04.01.09 15:27
Оценка: 2 (2)
Здравствуйте, NotGonnaGetUs, Вы писали:

NGG>Гхм. Тут какое-то расхождение во взглядах на то, что такое монолитность

NGG>Мне как раз твоё решение видится монолитным кусоком кода, а моё комбинируется из нескольких классов для полученя нужного результата и каждый из этих классов может жить счастливой самостоятельной жизнью.

Так как в функциональных языках функция первоклассная сущность, твое высказывание перепишется так:

а моё комбинируется из нескольких функций для полученя нужного результата и каждая из этих функций может жить счастливой самостоятельной жизнью.


Re[12]: Мастер-класс по ФП
От: VoidEx  
Дата: 04.01.09 15:43
Оценка:
Здравствуйте, NotGonnaGetUs, Вы писали:

NGG>Хитрожопую группу, которую простым фильтром не получить Н-р, нужно помнить состояние, а это меняет интерфейс группировалки...


NGG>Понятно, что "хорошее" решение, к которому я не смог бы придраться существует. Интересен принцип по которым оно строилось бы с полпинка.


На самом деле непонятно. Потому что появляются такие усложнения, которые скорее говорят о кривом решении некой другой задачи, раз появилась такая, где для группировки скоро придётся в базу данных обращаться, причём внутри самой группировалки.
Т.е. если вот приспичило цепочку собрать, так можно её и собрать, написав элементарную функцию, а не писать обобщённую группировалку, которая бы умела всё.

type Group a b = [a] -> ([([a], [a] -> b)], [a])
passFirst g s = g s
passAll g s = (fst $ g s, s)
makeGroup :: (Eq a) => ([a] -> [a]) -> ([a] -> b) -> Group a b
makeGroup f p l = ([(m, p)], l \\ m) where m = f l
composeGroup p f n [] = ([], [])
composeGroup p f n l = (fg ++ ng, ntail) where
    (fg, ftail) = p f l
    (ng, ntail) = p n ftail
seqGroup :: (Eq a) => Group a b -> Group a b -> Group a b
seqGroup = composeGroup passFirst
unionGroup :: (Eq a) => Group a b -> Group a b -> Group a b
unionGroup = composeGroup passAll

groupAndProcess input grouping = mapM_ (\x -> (snd x) (fst x)) $ fst $ grouping input

-- Остальное ниже - семечки, к делу не относящиеся
groupCmp cmp [] = []
groupCmp cmp l@(s:_) = filter (cmp s) l
groupByWith cmp x = seqGroup (makeGroup (groupCmp cmp) x) (groupByWith cmp x)

consoleOutput prefix input = putStrLn prefix >> mapM_ (putStrLn . ("\t" ++)) input

byFirstLetter :: String -> String -> Bool
byFirstLetter _ [] = False
byFirstLetter [] _ = False
byFirstLetter (l:_) (r:_) = l == r
groupStated f i l = map fst $ filter snd $ zip l $ fst $ runState (mapM f l) i
statedFilter :: String -> State String Bool -- группировалка со стейтом
statedFilter s = do
    lastStr <- get
    if ((null lastStr) || (null s) || ((last lastStr) == head s))
        then do
            put s
            return True
        else return False
input = ["abc", "cde", "efg", "aaa", "ghi", "sxdf", "zadedf", "sfsfg", "atrhyh", "43f5", "sdcsby", "Unuufd"]

main = groupAndProcess input $ unionGroup -- union, т.е. элементы попадут в обе группы
    (makeGroup (groupStated statedFilter "") (\xs@(x:_) -> consoleOutput [head x] xs)) -- составляем цепочку слов
    (groupByWith byFirstLetter (\xs@(x:_) -> consoleOutput [head x] xs)) -- группируем по первому символу

Смотря на всё это, делаю 3 вывода:
    1. Основной код всё равно невелик, 15 строк
    2. Либо всё это пишется проще на порядок (хотелось бы тогда от гуру увидеть подтверждение)
    3. И проще решать частные задачи по 2 строки на каждую, чем делать такое обобщение, которым и пользоваться не будет никто

Собственно, то же самое, но в частном случае:
byFirstLetter :: String -> String -> Bool
byFirstLetter _ [] = False
byFirstLetter [] _ = False
byFirstLetter (l:_) (r:_) = l == r

makeChain strs = reverse $ makeChain' strs "" [] where
    makeChain' [] cur acc = acc
    makeChain' (c:cs) cur acc
        | isPrefixOf cur c = makeChain' cs [last c] (c:acc)
        | otherwise = makeChain' cs cur acc
main = consoleOutput "chain" chain >> mapM_ (\xs@(x:_) -> consoleOutput [head x] xs) groups where
    (chain, groups) = (makeChain &&& (groupBy byFirstLetter . sort)) input
Re[6]: Мастер-класс по ФП
От: BulatZiganshin  
Дата: 04.01.09 15:46
Оценка:
Здравствуйте, NotGonnaGetUs, Вы писали:

BZ>>
BZ>>>>main = do readFile "words" >>== words >>== sort_and_groupOn (take 3) 
            >>>>>= mapM_ (\list -> writeFile (take 3 (head list)) (unwords list))

BZ>>


BZ>>несколько методов передать можно точно так же. насчёт контрактов я не понял — дай пример


и чем тебя не устраивает твоё решение?

BZ>>а почему моё решение комбинирует несколько функций для получения нужного результата, а твоё — монолитно? я думаю, причина в том, что в C* описание класса или даже функции — достаточно многословно, поэтому есть тенденция складывать в них больше функциональности, нежели в хаскеле


NGG>Гхм. Тут какое-то расхождение во взглядах на то, что такое монолитность

NGG>Мне как раз твоё решение видится монолитным кусоком кода, а моё комбинируется из нескольких классов для полученя нужного результата и каждый из этих классов может жить счастливой самостоятельной жизнью.

NGG>Само-то решение вот:

NGG>Где тут монолитность?

виноват, я в твоём решении просто не разбирался. имхо, оно ничем не отличается от моего, только я ес-но использую функции, а не классы. если к примеру тебе потребуется разбивать на классы 0..9 вместо a..z, то точно также придётся менять процитированный тобой код, как и в моём решении
Люди, я люблю вас! Будьте бдительны!!!
Re[13]: Мастер-класс по ФП
От: NotGonnaGetUs  
Дата: 04.01.09 15:58
Оценка:
Здравствуйте, dmz, Вы писали:

NGG>>вставив внутрь строчки для органиции потока данных по этой цепочке, я тоже разом решу все возможные проблемы?

dmz>Все возможные проблемы решить вообще невозможно. Эту задачу — да, вполне можно решить и так.
Ну так если затем расписать все перечисленные в аргуметах интерфейсы классы, получится тоже самое количество кода что в обрисованном мной вараинте.

dmz>А можно применить шаблон template method, например, а конкретные реализации параметризовать. Получится по смыслу почти то-же, что и в ФП примере.

Так оно влюбом варианте получится тоже самое по смыслу...

dmz>Очевидно, что у нас есть повторно используемые компоненты — источник (input) — который генерирует последовательность сущностей, filter, группирующая функция (считает некий ключ для этих сущностей), и консьюмер, да и сам алгоритм, в общем. Который в силу полиморфизма можно использовать для других объектов, для которых определены соответствующие компоненты.

+
NGG>>Если расписать всё это, получатся теже яйца, что и в оо варианте вид сбоку

IFilter — filter
IGroup#add — группирующая функция (не один к одному, т.к. есть разница между группами заданными из вне и группа создаваемыми в ходе работы алгоритма (как в решении с (take 3)). "Знание" о таких группах находится в реализации CompositeGroup и там может и должен использовать дескриминатор строящий по данным группу)
IProcessor — консьюмер
СompositeGroup — сам алгоритм

Разве не яйца?

dmz>Очевидно, что неверно про раз и навсегда заданные задачи.

Наверное, очевидным должно быть, что не только для раз и на всегда заданных условий, а для более широго круга задач
Вот собственно поддтверждения этому я и хочу найти.

NGG>>Ну, так я и прошу озвучить в чём же этот подход заключается, ... Станет ли он сразу не эффективным и почему?

dmz>Да потому, что язык не поддерживает.
А что он должен поддреживать? Только анонимные функции? Т.е. в C# уже на ура будет работать?

dmz>Честно говоря, приплетать опять грасп к этой задаче — это уже слишком.

Они приплетались не к этой задаче, а к вопросу о том с каким самоваром я лезу в фп
Куда, н-р, денешься от того, что есть точки не устойчивости в программах? Надо же как-то с этим бороться. В ООП интерфейсом отгараживаются, в ФП тоже как-то нужно бороться.

dmz> Ну вот пример — был у нас фильтр непустых строк, но, допустим, надо бы отсортировать комментарии и вообще — уметь наложить вместо одного фильтра N фильтров, но фильтры известны в компайл-тайме. Ну, в общем, вполне себе допущение, не хуже уже прочих.


dmz>Решение на ОО (оппа, группового наложения мы сразу не не предусмотрели? Ну, не беда)

dmz>
dmz>class MegaFilter : Filter 
dmz>{
dmz>};
dmz>


Гхм. Это вообще-то называется AndFilter и его добавление не приводит к изменниям в коде. Тот самый OCP в действии
Реализовывать его, пока он не был нужен и было бы овердизайном и заточкой под изменения, которые никогда не случатся (в отличии от декларации интерфейсов).

dmz>Решение три — рефакторим интерфейсы

Давайте без этого

NGG>>то в чём его плюсы перед имеющимся в наличии ООД? Если плюсы есть, то я стану использовать его в повседневной работе и буду рад безмерно.

NGG>>Согласен полностью. Простые. Но я же смог показать на простой задаче применение ОО-дизайна.
dmz>В итоге имеем овердизайн.
+1024.
Только цель предложенного дизайна была не показать как ооп крут, а фп гавно (такое ощущение, что многими, кто мне отвечал, оно воспринимается именно так). В том сообщении я задал вопрос про то, как выглядело бы решение в функциональном стиле будь это не задачка на две строчки, а "реальная" задача. ОО-код служит примером того, как я ответил бы на этот вопрос задай мне его кто-нибудь. Просто иллюстрация, чтобы было понятно о чём я спрашиваю. Похоже канал коммуникации этим приёмом настроить не удалось

dmz> из постановки очевидно, что "принять набор сущностей, отфильтровать, сгруппировать и и отдать консьюмеру" — это не есть сама задача — это решение некоей задачи.

Да как сказать... не очень очевидно

dmz> если задача решается в одну-две строки — то очевидно, если ВДРУГ, когда нибудь, в следующей жизни потребуются некоторые модификации, то две строчки проще выкинуть и написать заново, если уж на то пошло.

Опять +1024, но я уже тоже об этом раз 5 упомянул в своих ответах.

dmz> Как думаете, он будет вникать в весь "повторно использованный код" ? Или проведет "рефакторинг" — т.е. выкинет или забьет, и напишет свое?

Оффтоп:
Вот я сейчас в роли такого человека оказался. Перед глазами три "фреймоврка" для "легкого" построения гуя в одном приложение и все настолько безобразны (7+ лет приложению), что я плачу. Уже давно мечтаю всё выкинуть и написать своё, бо цена рефакторинга почти такая же, но если текущая задача стоит Х, переписать и выполнить текущую задачу "красиво" будет стоить 100*X, если не больше. Приходится закрывать глаза и получать удовльствие
Собственно эта ситуация отчасти поспособствовала тому, что я стал задавать тут глупые вопросы. Стало интересно, что было бы, пиши это приложение в течении 7 лет теже недалёкие люди, но только на функциональном языке. Больше гавна пришлось бы разбирать или меньше?

dmz>Особенно хорошо становится, когда креативных людей больше одного — все читали гамму, лармана и фаулера, там столько паттернов...

Я боюсь, что "креативных людей" в оо-мире не больше, чем было бы в ф-мире стань он мейнстримом, только читали бы не эти книги, а всяких других умных людей

dmz>Я еще раскрою тему.

Жду с нетерпением
Re[15]: Мастер-класс по ФП
От: NotGonnaGetUs  
Дата: 04.01.09 16:12
Оценка:
Здравствуйте, dmz, Вы писали:

dmz>Но смотрю я не с точки зрения разработчика. Смотрю я, допустим, с точки зрения заказчика или аутсорс-менеджера. И вижу, что вместо задачи построения дискового индекса, которую я заказывал, мне впаривают фреймворк для (цитирую)


Вы передёргиваете. В данном случае, и заказчик и исполнитель я. И таких требований у меня нет.
Принять решение насколько нужно обобщать задачу без общения с заказчиком программист не должен. Это вне рамок его компетенции.

dmz>Что мы видим? Для того, что бы данным решением воспользоваться — нужно пользоваться контейнерным (по сути) классом Group (если у нас данные ходят в каком-нибудь обычном List — придется написать адаптер, какой — нибудь свой FromListProcessor, разобраться, чем отличаются Group от Processor с одинаковым интерфейсом (две разные сущности с внешне одинаковым поведением, тесно сцепленные), а потом еще вытащить свои данные из Group.


Неа, нужно будет только написать свой процессор, который будет результат представлять ввиде желаемого вам листа или кренделя с бубликом.
И никаких гвоздей.
К моменту завоевания мира эти реализации уже будет в составе фреймворка

dmz>И это вместо того, что бы тупо в лоб воспользоваться фундаментальными примитивами group, map, filter — которые будут работать с любыми списками (не знаю, как в джаве, но в питоне есть group, filter, map прямо вот в таком виде) — на которые данная задача естественно декомпозируется.


Кстати, да. В отличии от того же c# в java стандартных group,filter,map — нет. Писать самоделки не даёт отсутствие "компактного" синтаксиса для написания лямбд и понижение производительности связанное с копирование списков, что в сумме перевешивает выгоды от наличия таких методов. В 7-ой будут лямбы и, думается мне, обновятся соответствующим образом стандартные библиотеки.
Re[13]: Мастер-класс по ФП
От: NotGonnaGetUs  
Дата: 04.01.09 16:42
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

NGG>>Целиком и полностью согласен и нисколько с этим не спорю. Я только повторяю заезженную истину о том, что дьявол в деталях.

NGG>>Как делается настройка "и поведения, и данных"?
NGG>>Как повторно использовать "труды" настройки?

BZ>передачей их в качестве параметров

BZ>видимо, речь идёт о partial application?

Сарказм понятен, переформулирую вопрос.
Чтобы передать "в качестве параметров" нужно как-то создать эти парметры.
Как они будут создаваться?
Как избежать дублирования кода, если метод дергается из разных мест в коде со слегка различающимися параметрами?
Не дурак, понимаю, что общая логика должна быть вынесена методы.
Тогда почему в предлагаемых решениях они не вынесены?
Опять не дурак, опять понимаю, что на кой их выносить, если всё в одной строчке.

Ну так я же просил показать как будет выглядеть решение "боевой" задачи, как если бы это было решение, которое ждёт большее будущее и долгая история развития
У меня подозрение, что проделай вы всё это, вместо одной строчки было бы что-то похожее по количеству строчек на код VoidEх'a.

Ну раз этот поинт никому не интересен можно забить на мои вопросы.

BZ>4) нужен двухсторонний автовывод типов с автоматическим обобщением. этого тоже нет, что затрудняет разбиение алгоритмов на множество небольших [глобальных, локальных и анонимных] функций — засребёшься описывать типы всех их параметров и результатов

Кстати, да. Декларации типов с генериками могут засрать код хорошо... Даже без относительно к фп хотелось бы такое иметь в наличии

BZ>удобно ли это? на мой взгляд нет — нужно сгруппировать описание контрола, перевод данных в него и обратно. соответственно ФП-дизайн здесь состоит в создании высокоуровневых контролов, которые несут в себе не только свои данные, но и ассоциированные с ними действия. и тогда программа будет выглядеть так:

BZ>
BZ>runDialog [
BZ>  Editbox [Color := Red, Label := "Speed", Init := (do setText =<< readVar speed), 
BZ>                                           OnOK := (do getText >>= writeVar speed)]
BZ>  SpinButton ....
BZ>]
BZ>


Пока гуй простецкий это работает. Пробовал на практике, для java есть возможность так писать используя Groovy и JavaFX. Но как только действия становятся сложнее, чем простое присвоение значения и когда контролы зависят друг от друга многими связями, плюсов станосится как-то заментно поменьше... mvc опять начинает рулить.

Но подход "dsl средствами языка" мне тоже нравится. Жаль, что в синтаксис java досточно убог для его широкого применения. Жду java7, где обещают быть улучшения в этом плане.
Re[3]: Мастер-класс по ФП
От: NotGonnaGetUs  
Дата: 04.01.09 16:54
Оценка:
Здравствуйте, dmz, Вы писали:

dmz>Слать это в сокет очень полезно, без сомнения. А вот сделаем реалистичное допущение относительно данной задачи в рамках ее предметной области (уж какая есть) — писать в каждый файл только уникальные строки (т.к. на кой черт писать дублирующие?)


dmz>решение на условном ФП:

dmz>concrete_filter = unique . filter filt
dmz>[/code]

Тоже самое на условной java:
class UniqueFilter<T> implements IFilter<T> {
    private Collection<T> uniqueData = ...
    UniqueFilter(IFilter<T> filter) {
       ...
    }
    
    UniqueFilter() {
       ...
    }

    boolean add(T t) {
       ...
    }
}


Re[14]: Мастер-класс по ФП
От: dmz Россия  
Дата: 04.01.09 17:23
Оценка:
NGG>Ну так если затем расписать все перечисленные в аргуметах интерфейсы классы, получится тоже самое количество кода что в обрисованном мной вараинте.

В джаве — да. За нее я и не говорю.

NGG>>>Если расписать всё это, получатся теже яйца, что и в оо варианте вид сбоку


Что в ФП варианте можно расписать? Приводился — ранее — вполне рабочий код.

NGG>СompositeGroup — сам алгоритм


Спорная вещь — засовывания алгоритма в класс, который выглядит как контейнерный...

NGG>Разве не яйца?


И как-то очень много.

NGG>Наверное, очевидным должно быть, что не только для раз и на всегда заданных условий, а для более широго круга задач

NGG>Вот собственно поддтверждения этому я и хочу найти.

Ну какие нужны подтверждения? Когда меняется ситуация, редактировать ФП код как-то проще, поскольку его обычно меньше. Общие вещи, абстракции — выделяются и выносятся. Рассуждать 'в общем' мне тяжело — лучше на конкретных примерах. Вот есть у меня компилятор, который пережил несколько смен синтаксиса и еще переживет. Там нет ничего, что можно было бы унаследовать, и создать, например, новый компилятор путем наследования и подмешивания к существующему. Плохо ли это? Нет, это только хорошо.

NGG>А что он должен поддреживать? Только анонимные функции? Т.е. в C# уже на ура будет работать?


Ну вот, композицию функций, например. Алгебраические типы. Паттерн-матчинг.

dmz>> Ну вот пример — был у нас фильтр непустых строк, но, допустим, надо бы отсортировать комментарии и вообще — уметь наложить вместо одного фильтра N фильтров, но фильтры известны в компайл-тайме. Ну, в общем, вполне себе допущение, не хуже уже прочих.


NGG>Гхм. Это вообще-то называется AndFilter и его добавление не приводит к изменниям в коде. Тот самый OCP в действии


Его написать надо, или его можно сгенерировать из имеющихся фильтров? Или есть конструкция AndFilter<FilterA, FilterB, ...> которая его породит?

NGG>Реализовывать его, пока он не был нужен и было бы овердизайном и заточкой под изменения, которые никогда не случатся (в отличии от декларации интерфейсов).


Ну так impact, который получится при таком изменении требований — он в итоге разный в ФП и ООП?


NGG>Только цель предложенного дизайна была не показать как ооп крут, а фп гавно (такое ощущение, что многими, кто мне отвечал, оно воспринимается именно так). В том сообщении я задал вопрос про то, как выглядело бы решение в функциональном стиле будь это не задачка на две строчки, а "реальная" задача.


Как можно показать решение "не на две строчки" в двухстрочной задаче?

NGG>ОО-код служит примером того, как я ответил бы на этот вопрос задай мне его кто-нибудь. Просто иллюстрация, чтобы было понятно о чём я спрашиваю. NGG>Похоже канал коммуникации этим приёмом настроить не удалось


Ну, наверное, не лучший пример. Не знаю, где взять лучший. Попробую сформулировать свою позже.

NGG>Вот я сейчас в роли такого человека оказался. Перед глазами три "фреймоврка" для "легкого" построения гуя в одном приложение и все настолько безобразны (7+ лет приложению), что я плачу. Уже давно мечтаю всё выкинуть и написать своё, бо цена рефакторинга почти такая же, но если текущая задача стоит Х, переписать и выполнить текущую задачу "красиво" будет стоить 100*X, если не больше. Приходится закрывать глаза и получать удовльствие


Объем задачи другой. Но ведь тут уже ничего не поможет — ни фп, ни ооп.

NGG>Собственно эта ситуация отчасти поспособствовала тому, что я стал задавать тут глупые вопросы. Стало интересно, что было бы, пиши это приложение в течении 7 лет теже недалёкие люди, но только на функциональном языке. Больше гавна пришлось бы разбирать или меньше?


Все также зависит от человеческого фактора. ФП — очень мощный инструмент. В правильных руках — он послужит сокращению сроков и издержек. Но не в тех руках — оно будет только во вред. Преимущество ФП в том, что в нем есть встроенная защита от дурака. Недостаток ФП в том, что дурак, обошедший эту защиту — стоит сотни обычных по разрушительным последствиям.

Инструмент нужно выбирать по задаче. Для меня в моих условиях — ФП является более выгодным инструментом. Для кого-то — вероятно, нет.
Как мне кажется — ФЯ являются более мощными и более высокоуровневыми, по сравнению с распространенными обычными языками.
Re[4]: Мастер-класс по ФП
От: dmz Россия  
Дата: 04.01.09 17:25
Оценка:
dmz>>решение на условном ФП:
dmz>>concrete_filter = unique . filter filt
dmz>>[/code]

NGG>Тоже самое на условной java:


Не говоря о том, что здесь всего больше, мне как-то неочевидно, как это должно использоваться.
Re[5]: Мастер-класс по ФП
От: Аноним  
Дата: 04.01.09 21:00
Оценка:
Здравствуйте, dmz, Вы писали:

dmz>Не говоря о том, что здесь всего больше, мне как-то неочевидно, как это должно использоваться.


вместо new FilterImp(...) ставится new UniqueFilter(new FilterImpl()) и используется. FilterImpl это реализация фильтра, который нужно сделать уникальным...
Re[6]: Мастер-класс по ФП
От: dmz Россия  
Дата: 05.01.09 05:26
Оценка:
А>вместо new FilterImp(...) ставится new UniqueFilter(new FilterImpl()) и используется. FilterImpl это реализация фильтра, который нужно сделать уникальным...

Предложенный интерфейс фильтра подразумевает, что он применяется к одному элементу:

interface IFilter<T>
{
    boolean match(T t);
}


и в реализации так и происходит. Уникальные элементы таким образом не отфильтруешь.
Re[6]: Мастер-класс по ФП
От: geniepro http://geniepro.livejournal.com/
Дата: 05.01.09 05:53
Оценка:
Здравствуйте, NotGonnaGetUs, Вы писали:

NGG>Использование функции c не безопасно — н-р, можно при правке кода поменять a на a', а про b забыть...

NGG>Компилятор промолчит. Может быть даже тесты пройдут успешно, т.к. разница между b и b' крылась в каком-то редком случае почему-то не покрытому при тестировании. А в итоге приложение не отработает как следует в самый ответственный момент.

Ну и что тут необычного? Это постоянно происходит в любых языках и парадигмах -- ФП, очевидно, не является серебрянной пулей.
Конкретно с этой проблемой может быть могут немного уменьшить опасность зависимые типы, когда их сделают простыми для использования. И то не на 100%...

NGG>Возможно моя боязнь блуждающих по аргументам в свободном полёте связных функций это только от недостатка опыта в их готовке...

NGG>Но пока мне кажется, что разумно было бы явно декларировать зависимость между аргументами:
NGG>
NGG>data Converter = Converter 
NGG>{
NGG>     encoder :: (Int->String), 
NGG>     decoder :: (String -> Int)
NGG>}

NGG>c :: Converter -> String(неважно что) -> String (в неважно что)
NGG>

NGG>Из декларации сразу видно что к чему.
NGG>Разве нет?

Ну Вам же никто не запрещает так делать? Нужно -- так делайте! Все возможности для этого у Вас есть...

NGG>Гхм. Тут какое-то расхождение во взглядах на то, что такое монолитность

NGG>Мне как раз твоё решение видится монолитным кусоком кода, а моё комбинируется из нескольких классов для полученя нужного результата и каждый из этих классов может жить счастливой самостоятельной жизнью.

Делайте решение в ФП-стиле -- то есть кучу маленьких функций, максимально обобщённых. И тогда останется просто комбинировать их в нужном порядке -- вот и не будет этой страшной монолитности...
Re[4]: Мастер-класс по ФП
От: Tonal- Россия www.promsoft.ru
Дата: 05.01.09 05:59
Оценка: +1
Здравствуйте, BulatZiganshin, Вы писали:
BZ>как-то всё это сложно
Ну я это и нарисовал. Только использовал списковые дополнения вместо map-ов
Вместо mapMaybe (stripPrefix (make dir)) выписал списковое доплнение через take и drop для случая непустого имени (с монадами пока торможу).
mapSnd — тоже выписал явно.

По ходу есть ещё одно препятствие в изучении ФП, но оно довольно общее для любых языков — пока не очень свободно знаешь язык и его стандартные библиотеки, очень трудно распознать алгоритм в чужом коде.
И тем более предсказать трудоёмкость.
Например, решение через take и drop скорее всего проигрывает по сравнению с mapMaybe (stripPrefix (make dir)). По крайней мере в С/С++ я мог бы это отразить. Но как это в haskell-е я пока не в курсе.
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[13]: Мастер-класс по ФП
От: geniepro http://geniepro.livejournal.com/
Дата: 05.01.09 06:20
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

BZ>вот пример. представим классическую gui-библиотеку. реализация диалога настроек на ней может выглядеть так:

BZ>1) создаём все необходимые controls
BZ>2) заполняем их исходными данными
BZ>3) отображаем диалог
BZ>4) после нажатия Ok обновляем переменные

BZ>удобно ли это? на мой взгляд нет — нужно сгруппировать описание контрола, перевод данных в него и обратно. соответственно ФП-дизайн здесь состоит в создании высокоуровневых контролов, которые несут в себе не только свои данные, но и ассоциированные с ними действия. и тогда программа будет выглядеть так:

BZ>
BZ>runDialog [
BZ>  Editbox [Color := Red, Label := "Speed", Init := (do setText =<< readVar speed), 
BZ>                                           OnOK := (do getText >>= writeVar speed)]
BZ>  SpinButton ....
BZ>]
BZ>


Кстати, вот животрепещущая тема (для меня), можете посоветовать что-нить в этом плане? Имею в виду сами принципы построения такого фреймворка применительно к Хаскеллу. Всякие там Model-View-Controller в функциональном стиле...
Re[5]: Мастер-класс по ФП
От: FR  
Дата: 05.01.09 06:25
Оценка:
Здравствуйте, Tonal-, Вы писали:

T>По ходу есть ещё одно препятствие в изучении ФП, но оно довольно общее для любых языков — пока не очень свободно знаешь язык и его стандартные библиотеки, очень трудно распознать алгоритм в чужом коде.


С ФП с этим полегче по моему. Вот при изучении Smalltalk у человека знающего майнстримный ООП приключается когнитивный диссонанс
Re[12]: Мастер-класс по ФП
От: Tonal- Россия www.promsoft.ru
Дата: 05.01.09 07:02
Оценка:
Здравствуйте, NotGonnaGetUs, Вы писали:
dmz>process inp filt group_by consume = inp >>> filter filt >>> group group_by >>> consume

NGG>А если я напишу класс
NGG>сlass TaskNumberOne {
NGG>void process(Source inp, Filter filt , Group group_by, Consumer consume)  {...}
NGG>}

Для того, чтобы код был аналогичен, нужно однако чуть добавить:
сlass TaskNumberOne {
  template <class Source, class Filter, class Group, class Consumer>
  void process(Source inp, Filter filt, Group group_by, Consumer consume)  {...}

Тогда мы можем воспользоваться "трудами" фильтра в группировке, только они должны имеь согласованный интерфейс.
При этом возникает ещё 2 типа — то что получилось после фильтрации и то, что получилось после группировки. Но если попытаться их здесь явно выписать, то получаются уже шаблоны шаблонов и сигнатура получается монстрообразная, а на Java или C# просто невыразимая...
... << RSDN@Home 1.2.0 alpha 4 rev. 0>>
Re[14]: Мастер-класс по ФП
От: geniepro http://geniepro.livejournal.com/
Дата: 05.01.09 07:08
Оценка:
Здравствуйте, NotGonnaGetUs, Вы писали:

NGG>Ну так я же просил показать как будет выглядеть решение "боевой" задачи, как если бы это было решение, которое ждёт большее будущее и долгая история развития

NGG>У меня подозрение, что проделай вы всё это, вместо одной строчки было бы что-то похожее по количеству строчек на код VoidEх'a.

В таких проектах объём документации должен быть на порядок больше объёма кода, иначе проблемы будут всегда. И комментарии в коде должны быть обширными. И вапще Literate Programming тут уже напрашивается.
В итоге подходим к тому, что программа должны быть исполняемым руководством...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.