LINUX.ORG.RU

Вышел 2-й выпуск журнала «Практика функционального программирования»

 , , ,


1

0

Вышел в свет второй выпуск журнала «Практика функционального программирования».

Центральная тема второго выпуска журнала — демонстрация применения функционального программирования в реальных, а не академических проектах.

Первые четыре статьи — Дмитрия Зуйкова, Дмитрия Астапова, Сергея Зефирова в соавторстве с Владиславом Балиным, и Алексея Отта — вытаскивают на поверхность «кухню» нескольких компаний. Статьи демонстрируют, что функциональные языки находят применение в промышленном программировании в самых разных нишах. Конечно, использование «нестандартных» языков накладывает на проекты некоторые сложно оценимые риски, и далеко не все из них рассмотрены в статьях. Но если статьи этого номера позволят развеять хоть часть сомнений, мифов и предрассудков и поднять дискуссию о применимости функциональных языков в промышленном программировании на новый уровень, мы будем считать свою задачу выполненной.

Статья Александра Самойловича рассматривает создание на языке Erlang игрушечного, но практичного проекта — рекурсивного многопоточного обходчика сайтов. К третьему выпуску журнала мы планируем подготовить ещё несколько статей про Erlang.

Завершающая статья Романа Душкина в большей степени ориентирована на теорию: она познакомит вас с концепцией алгебраических типов данных (АТД) в Haskell и других функциональных языках.

>>> Подробности

★★★★★

Проверено: maxcom ()
Последнее исправление: maxcom (всего исправлений: 1)
Ответ на: комментарий от tailgunner

>Делаешь метод set_state или проперть state, и проверяешь.

Не ерунда. Этот подход изолирует только внешний мир - что мешает написать еще десяток методов в этом объекте (без сомнения полезных и функциональных). Как ты будешь дальше гарантировать что эти методы "до нас" никто не вызывал и они не перехерачили объект до неузнаваемости?

Инкапсуляция в смысле сокрытия роеализации - это как договор программиста сам с собой что он в функцию факториала просто не будет передавать отрицательные числа - тогда и ошибок не будет.

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

>Ну вот такой граф переходов у яйца, я же не виноват в том, что вы выбрали такой пример.


Wake Up, Neo. Welcome to the Real World :)

>В случае ФП, IIUC, она происходит при создании нового объекта, но проверка всё равно делается.


Вон там пример с яйцами сломать его изнутри можно только в одном месте (надо одну строчку дописать чтобы полечить). Сннаружи он железобетонный. Сколько с++нго кода займет реализовать то же самое?

>А мне кажется, дело в том, что ФП создает тупо больше типов :)


Да - иммутабельных типов, манипуляция которыми осущществляется посредством чистых функций. Поломать яичницу на хаскеле нельзя именно по этой причине. Эта пара там реализует "систему уроанений" которая описывает именно упомянутые транзишены данных - они не "возвращаемые" и потому там нет "бракованных" инвариантов.

Представь что у тебя в обектном языке на уровне языка поддерживалось бы.

e = new RawEgg().break()

где
e instanceOf BrokenEgg
e !instanceOf RawEgg
e hasNot method break //поэтому семантика нового иснстанса d ghbywbgt не позволит все сломать

То есть транзишены объектов (как это и происходит в реальном мире - скорлупа это уже не яйцо). На императивном объектном языке таку шнягу можно реализовать. Вся фигня в том в результате будем иметь немутабельные структуры данных и чистые функции - тадаа!:)) Только в крайне неудобной форме.

То есть декларация иммутабельных структур + набор чистых функций - дает _полное_ описание модели данных. А злобный компилятор камла при паттерн матчинге даже ругаться умеет на тему "перечислены не все возможные варианты".

К стати упомянутый граф переховдов для реализации проверки инвариантов (объектный паттерн полиморфная "стратегия", для того чтобы в каждом методе в очередной раз не проверять N некорректных состояний при вызове), будет сильно попахивать континуэшеном и монадами.

>Только вот не сказать, что Ява или Си++ сильно похожи на Смолток.


Они пытаются исправиться:)


r ★★★★★
()
Ответ на: комментарий от r

> То есть декларация иммутабельных структур + набор чистых функций - дает _полное_ описание модели данных.

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

//yet another anonymous

anonymous
()
Ответ на: комментарий от r

>А мне кажется, дело в том, что ФП создает тупо больше типов :)

>>Да - иммутабельных типов


В ООП используется концепция класс-как-тип. Наверно самая плохая черта ООП. Правда, можно насоздавать пустых static классов (Александреску так делает) и молиться чтобы компилятор оптимизировал. И ессно в уме программистов возникает цепочка, если класс - значит объект, если объект - то память и накладные расходы на создание.

И самое смешное что в любом уважающем себя ООП проекте типов обычно более 9000, если считать классы, интерфейсы, обертки интерфейсов и т.п. за таковые.

Лично мне было странно осознавать тот факт, что типы в ML языках существуют "просто так" без интерфейса и не определяют поведение.

Другой не очень хорошей чертой, правда отдельных реализаций ООП, является то, что объект не может существовать "сам по себе". В Скале это можно сделать через ключевое слово object, в плюсах - с помощью синглетонов. Но синглетоны - это такое дело: ты их создавал, тебе же их убивать, что вызывает большие сложности.

Macil ★★★★★
()
Ответ на: комментарий от anonymous

>осознавать ключевую идею ФП

Ключевая идея ФП - все есть функция.

В ФП нет объектов, в том виде как это понимается в ООП. В ООП класс тройственен: класс-как-тип, класс-как-интерфейс и класс-как-поведение. Классы выстраиваются в иерархию, по "общности" признаков, т.е. иерархическая декомпозиция предметной области.

Соответственно, каждый класс в иерархии определяет тип, часть интерфейса, и часть поведения объекта.

За все ФП языки не скажу, но в ML-подобных такого просто нет. Там тип, интерфейс и поведение существуют абсолютно независимо. Именно поэтому идиомы из мира ООП в таких языках не только бесполезны, но иногда и вредны.

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

Macil ★★★★★
()
Ответ на: комментарий от anonymous

> В терминах ООП получается, что каждый мутатор - это фабрика новых объектов отличного или того же типа. Верно я понимаю?

ИМХО, ключевая идея как раз в том, что мутатор производит объект другого типа, и система типов позволяет отлавливать ошибки, связанные с неправильным использованием.

tailgunner ★★★★★
()
Ответ на: комментарий от r

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

Да ты чо? Т.е. в функции факториала на фп языке _не надо_ проверять передается ему отрицательное число или нет, там это делается все automagically?

[code]

fact :: Integer -> Integer fact 0 = 1 fact n = n * fact (n-1)

*Main> fact (-5) -5 *Main> fact (5) 120 [/code]

> Вон там пример с яйцами сломать его изнутри можно только в одном месте (надо одну строчку дописать чтобы полечить). Сннаружи он железобетонный. Сколько с++нго кода займет реализовать то же самое?

что значит сломать "изнутри" или "снаружи"? Почему ты все время сравниваешь с намного более низкоуровневым си++ и явой? Я тебе с таким же успехом могу доказать превосходство ооп, сравнивая ассемблер и си++.

> На императивном объектном языке таку шнягу можно реализовать. Вся фигня в том в результате будем иметь немутабельные структуры данных и чистые функции - тадаа!:))

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

anonymous
()
Ответ на: комментарий от anonymous

> Да ты чо? Т.е. в функции факториала на фп языке _не надо_ проверять передается ему отрицательное число или нет, там это делается все automagically?

Перечитай еще раз то что я сказал.

>Почему ты все время сравниваешь с намного более низкоуровневым си++ и явой?


Я сравниваю с императивными языками. Межешь попробовать более "высокоуровневыми". Суть в том что реализация должна быть парадигматическая.

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


Ты можешь хооть одну фразу обосновать - а не оборвать на месте "это не так". А как?

r ★★★★★
()
Ответ на: комментарий от r

> Не ерунда. Этот подход изолирует только внешний мир - что мешает написать еще десяток методов в этом объекте (без сомнения полезных и функциональных). Как ты будешь дальше гарантировать что эти методы "до нас" никто не вызывал и они не перехерачили объект до неузнаваемости?

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

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

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

PS. я так и не понял твоего примера с "транзишеном", да и вообще у меня лично складывается впечатление, что мы друг друга сильно недопонимаем.

anonymous
()
Ответ на: комментарий от anonymous

>Точно также, тебе нужно будет это проверять.

О май факин год.

10 x = some
20 y = f1(x)
30 z = f2(x, y)

Если это хаскел я тебе точно скажу чему равен X в третьей строчке. Если это императивный язык - ты мне в жизни этого не гарантируешь. Доходчиво?

>Я тебе уже приводил пример с функцией unfry - почему в твоем любимом функциональном хаскелле даже просто возможна фукнция, противорящая т.н. тобой инварианту?


потому что для этого надо _специально_ выстрелить в ногу написав специальную функцию - что ты и сделал. А если приведенный выше код на императивном языке - чему равен X в третьей строче? Правильный ответ - "хрен его знает".

>Причем это будет даже сильнее,


Жду с нетерпением!

>PS. я так и не понял твоего примера с "транзишеном"


Время. Возвращаясь к образу мышления человеку и реальному миру - тут есть такой параметр как время и мир обратно не возвращается. Ты не можешь в реальности вернуть яйцу состояние "целое". А в императивной модели - можешь. Именно потому она лдч человека неестественна - процессы которые проистекают вокруг человека - невозвращаемы. В общем случае объекты не переходят в любые "состояния" в которых потенциально могут быть. Потому что по сути это _не состояния_. Это превращение одних объектов в другие.

r ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.