Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.217.60.35] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Люди умеющие работать с функциональными ЯП, объясните, как
Например класс содержащий какие-то там поля-свойства и методы. Как этот объект представляется в функциональных языках? Посмотрим на Erlang, педивикия пишет, что можно задействовать кортеж, но можно ли обратиться к элементам кортежа по именам полей? Как реализовать всякие методы? Делать кучу глобальных функций принимающих в качестве первого аргумента объект, как в старом добром C? |
Сообщ.
#2
,
|
|
|
Цитата applegame @ объект с полями и указателями на методы, если совсем кратко Делать кучу глобальных функций принимающих в качестве первого аргумента объект, как в старом добром C? |
Сообщ.
#3
,
|
|
|
Цитата SVK @ И как создать такой объект? Можно простейший пример на том же Erlang? объект с полями и указателями на методы, если совсем кратко |
Сообщ.
#4
,
|
|
|
Цитата applegame @ 1) Люди умеющие работать с функциональными ЯП, объясните, как 2) Например, класс содержащий какие-то там поля-свойства и методы. 3) Как этот объект представляется в функциональных языках? 4) Посмотрим на Erlang, педивикия пишет, что можно задействовать кортеж, но можно ли обратиться к элементам кортежа по именам полей? 5) Как реализовать всякие методы? Делать кучу глобальных функций принимающих в качестве первого аргумента объект, как в старом добром C? 1) В общем случае никак, это же другой подход, без объектов. В частных случаях — с помощью замыканий, например. 2) Это не пример. Программирование существует не ради программирования, а объекты не ради объектов. 3) См. пункт 1. 4) У кортежа нет имён полей, не понимаю, о чём ты. 5) См. пункт 1. Все ответы на твои вопросы есть в SICP: Lecture 6A Lecture 6B |
Сообщ.
#5
,
|
|
|
Цитата SVK @ Цитата applegame @ объект с полями и указателями на методы, если совсем краткоДелать кучу глобальных функций принимающих в качестве первого аргумента объект, как в старом добром C? Ты функциональное программирование с процедурным не путаешь? Какие указатели в функциональном программировании? Добавлено applegame, может начать со scala/f#, просто оставить классы на какое-то время и посмотреть, к чему в итоге придёт проект? Добавлено Цитата applegame @ Например класс содержащий какие-то там поля-свойства и методы. Как этот объект представляется в функциональных языках? В функциональных языках лучше это никак не представлять, а спроектировать другое решение исходной задачи. |
Сообщ.
#6
,
|
|
|
Цитата korvin @ Это из педивикии, что-то я не так понял видимо:4) У кортежа нет имён полей, не понимаю, о чём ты. Цитата Wikipedia..Erlang.Кортеж Что такое кортеж, объяснять не нужно.В Erlang принято строить различные типы данных на основе кортежей с тегами, что облегчает отладку программы и считается хорошим стилем программировани Цитата korvin @ 1) В общем случае никак, это же другой подход, без объектов. В частных случаях — с помощью замыканий, например. Цитата D_KEY @ В функциональных языках лучше это никак не представлять, а спроектировать другое решение исходной задачи. Я об этом, по сути, и спрашиваю. Смотришь на всякие учебники для новичков, а там туфта вроде подсчета чисел Фибоначчи, сортировки списков, всяких map/reduce, которые есть в любом современном языке и нихрена функциональному подходу не учат. Поэтому и говорю о ломании шаблона. Я при проектировании задачи сразу начинаю мыслить объектами. Как от этого уйти? Допустим простейший игровой сервер, где есть карта, есть NPC бродящие по этой карте и игроки. Ну вот как это спроектировать без ООП, ума не приложу? Ну карта - двумерный массив, а мобы и игроки? Добавлено Цитата D_KEY @ Да, я тоже подумал что что-то недопонято. Я ковырял в свое время игровой сервер написанный целиком на C. Но там один хрен было ООП, как раз через поля структур в виде указателей. Там даже было наследование этих структур сымитировано через касты. Ты функциональное программирование с процедурным не путаешь? Какие указатели в функциональном программировании? |
Сообщ.
#7
,
|
|
|
D_KEY: да, попутал %)
|
Сообщ.
#8
,
|
|
|
Цитата korvin @ А на русском есть что-нибудь подобное. Я тяжело воспринимаю английский на слух. Все ответы на твои вопросы есть в SICP: Добавлено Вот нашел первое попавшееся - http://www.youtube.com/watch?v=Ze6qdlyz-30 буду посмотреть. |
Сообщ.
#9
,
|
|
|
Цитата applegame @ Цитата korvin @ А на русском есть что-нибудь подобное. Я тяжело воспринимаю английский на слух.Все ответы на твои вопросы есть в SICP: Ну книга SICP переведена на русский("структура и имплементация компьютерных программ"). Но я бы тебе ее рекомендовать не стал... Она слишком базовая. В MIT этот курс был для CS, а не SE. Так что на счёт использования для начала функциональных языков, которые умеют ООП? Ocaml, F#, Scala. А там постепенно где видишь пользу от функционального программирования, там и используешь. Мне вообще кажется, что эти подходы вполне себе существуют вместе, на более высоком уровне у нас ОО-система, а на более детальном уровне функциональщина("конвейерная" работа с потоками данных, как можно меньше мутабельности, простое распараллеливание, сопоставление с образцом, алгебраические типы данных и пр.). Добавлено Цитата applegame @ Поэтому и говорю о ломании шаблона. Я при проектировании задачи сразу начинаю мыслить объектами. Как от этого уйти? Допустим простейший игровой сервер, где есть карта, есть NPC бродящие по этой карте и игроки. Ну вот как это спроектировать без ООП, ума не приложу? На последнем докладе о функциональщине, что я видел(вживую), докладчик рассматривал пример игры "жизнь". А потом спел песню про монады Ссылку могу дать чуть позднее. Там на русском. Добавлено Agile Days 2015, Вагиф Абилов: А нам-то зачем функциональное программирование? Цитата В докладе на простых примерах дается представление о том, чем отличается моделирование предметной области и реализация функционала при использовании функциональных языков - таких, как F#, Scala и Clojure, в сравнении с объектно-ориентированными C# и Java. Какие типы задач наиболее подходят для функциональных языков? Как их лучше внедрять в проект? И как убедить руководство в практичности такого выборы? Обо всем этом пойдет речь в докладе. Ну рассказал он не обо всем. Зато спел |
Сообщ.
#10
,
|
|
|
Цитата applegame @ Это из педивикии, что-то я не так понял видимо: Цитата Wikipedia..Erlang.Кортеж Что такое кортеж, объяснять не нужно.В Erlang принято строить различные типы данных на основе кортежей с тегами, что облегчает отладку программы и считается хорошим стилем программировани А, кортеж с тэгами, это другое дело. По сути это записи (records) =) Это уже зависит от конкретного языка, в Хаскелле, например, получить значения полей можно с помощью одноимённых функций-селекторов, которые автоматически генерируются при объявлении типа-записи. Не очень удобное решение, получается невозможно определить в одном модуле два типа-записи с одноимённым полем, будет конфликт имён. В Ocaml записи получше сделаны, ИМХО. Какой синтаксис в Erlang'е для работы с такими типами — ХЗ. Ну и конечно сопоставление с образцом (pattern matching), если у тебя не opaque-тип. Цитата applegame @ Я об этом, по сути, и спрашиваю. Смотришь на всякие учебники для новичков, а там туфта вроде подсчета чисел Фибоначчи, сортировки списков, всяких map/reduce, которые есть в любом современном языке и нихрена функциональному подходу не учат. Почитай Real World Haskell или Real World Ocaml (правда в Ocaml есть и классы с объектами, и сайд-эффекты можно использовать свободно, без контроля со стороны системы типов, поэтому Хаскелл в целом будет более нагляден). Там более практичные примеры. Цитата applegame @ Поэтому и говорю о ломании шаблона. Я при проектировании задачи сразу начинаю мыслить объектами. Как от этого уйти? Допустим простейший игровой сервер, где есть карта, есть NPC бродящие по этой карте и игроки. Ну вот как это спроектировать без ООП, ума не приложу? Ну карта - двумерный массив, а мобы и игроки? Записи. |
Сообщ.
#11
,
|
|
|
Цитата D_KEY @ Спасибо за ссылку, интересный и достаточно веселый доклад, хотя нового оттуда я мало чего почерпнул, скорее слегка углубил, то что уже знал. Кроме монад конечно. Я еще ими серьезно не занимался, а из доклада так и не понял разницу между исключениями и монадами. Также не совсем понял, что он там говорил об описании неких доменов. Это надо отдельно читать.Так что на счёт использования для начала функциональных языков, которые умеют ООП? Ocaml, F#, Scala. А там постепенно где видишь пользу от функционального программирования, там и используешь. Мне вообще кажется, что эти подходы вполне себе существуют вместе, на более высоком уровне у нас ОО-система, а на более детальном уровне функциональщина("конвейерная" работа с потоками данных, как можно меньше мутабельности, простое распараллеливание, сопоставление с образцом, алгебраические типы данных и пр.). Agile Days 2015, Вагиф Абилов: А нам-то зачем функциональное программирование? Цитата В докладе на простых примерах дается представление о том, чем отличается моделирование предметной области и реализация функционала при использовании функциональных языков - таких, как F#, Scala и Clojure, в сравнении с объектно-ориентированными C# и Java. Какие типы задач наиболее подходят для функциональных языков? Как их лучше внедрять в проект? И как убедить руководство в практичности такого выборы? Обо всем этом пойдет речь в докладе. Ну рассказал он не обо всем. Зато спел В качестве небольшого упражнения переписал F# код для игры Жизнь из лекции Абилова на D (фактически портирование): Игра жизнь на D в функциональном стиле import std.range; import std.typecons; import std.algorithm; import std.functional; import std.container; // возвращает список соседей клетки auto neighbours(C)(C cell) { return iota(-1,2) .map!(i => iota(-1,2) .map!(j => tuple(cell[0]+i, cell[1]+j))) .joiner .filter!(c => c != cell); } // определяет жива ли клетка (клетка жива, если она есть в популяции) bool isAlive(P, C)(P population, C cell) { return population .canFind(cell); } // возвращает список живых соседей клетки auto aliveNeighbours(P, C)(P population, C cell) { return cell .neighbours .filter!(curry!(isAlive, population)); } // определяет выживет ли клетка в следующей итерации bool survives(P, C)(P population, C cell) { return population .aliveNeighbours(cell) .walkLength.among(2, 3) > 0; } // определяет родится ли клетка в следующей итерации bool reproducible(P, C)(P population, C cell) { return population .aliveNeighbours(cell) .walkLength == 3; } // возвращает список всех "мертвых" соседей всех клеток популяции auto allDeadNeighbours(P)(P population) { return population .map!neighbours .joiner .make!RedBlackTree[] .filter!(not!(curry!(isAlive, population))); } // возвращает следующее поколение популяции auto nextGeneration(P)(P population) { // соединяем списки всех выживших и родившихся клеток return chain( population .filter!(curry!(survives, population)), population.allDeadNeighbours .filter!(curry!(reproducible, population)) ); } void main() { import std.stdio; import std.typecons; immutable population = [tuple(-1,0), tuple(0,0), tuple(1,0)]; population.nextGeneration.writeln; } В целом, функциональным подходом на уровне вышеприведенного кода я и так активно пользуюсь в своих проектах, включая иммутабельность (как раз ради эффективного распараллеливания без синхронизации между потоками). С игрой Жизнь все понятно, вычичление новой итерации - чистая функция. Получили на вход список, вернули новый список. Результат строго детерминирован от входных данных. Но вот типа на Erlang пишут распределенные системы, веб-сервера и все такое. В веб-сервере запросы зачастую не могут быть чистыми функциями, например запись в БД - вполне себе сайд-эффект. Что-то мне подсказывает что тут-то и начинается расколбас с монадами. Это так? Добавлено Еще вот интересный момент: у Абилова в примере с игрой Жизнь, в функции создания списка соседей присутствуют циклы. Разве в труЪ функциональном подходе циклы в традиционном понимании используются? |
Сообщ.
#12
,
|
|
|
Цитата applegame @ 1) Но вот типа на Erlang пишут распределенные системы, веб-сервера и все такое. В веб-сервере запросы зачастую не могут быть чистыми функциями, например запись в БД - вполне себе сайд-эффект. Что-то мне подсказывает что тут-то и начинается расколбас с монадами. Это так? 2) Еще вот интересный момент: у Абилова в примере с игрой Жизнь, в функции создания списка соседей присутствуют циклы. Разве в труЪ функциональном подходе циклы в традиционном понимании используются? 1) Монады как бы не при чём. В Clean, нет монад, например, для сайд-эффектов используются unique types (или как-то так). Монада (в Хаскелле) — это всего лишь интерфейс, определяющий некоторые методы работы с данными. Если проводить аналогии с реальным миром, то это такая коробка, положив какой-то объект в которую, ты не можешь просто достать его, ты можешь только достать объект, что-то с ним сделать и положить в такую же коробку. Монада IO в этом плане несколько особенная, хотя язык не регламентирует её реализацию в исполнителе, но именно IO используется исполнителем, для реализации взаимодействия с внешним миром. В Erlang'е монад нет, а интерфейс работы с БД может выглядеть и использоваться вполне себе функционально, ведь все сайд-эффекты как бы находятся во внешнем мире. «let (rows, err) = db.select(query, param...) in ...» — выглядит вполне себе функционально. «let err = db.exec("UPDATE ...", param...) in ...» тоже. 2) Не используются. Но синтаксис может позволять их выразить стандартными средствами, например forM_ в Хаскелле выглядит (и используется) как вполне себе цикл. Добавлено Вот тут, кстати, чел приводит пример, как в Хаскелле «реализуется ООП»: http://stackoverflow.com/questions/1310668...110560#13110560 Можешь ещё посмотреть на Functional Reactive Programming в Хаскелле, которое применяется для GUI, который обычно считается очень ООП-шной предметной областью. |
Сообщ.
#13
,
|
|
|
Цитата korvin @ Да, но ведь такая функция получается не "чистая".В Erlang'е монад нет, а интерфейс работы с БД может выглядеть и использоваться вполне себе функционально, ведь все сайд-эффекты как бы находятся во внешнем мире. «let (rows, err) = db.select(query, param...) in ...» — выглядит вполне себе функционально. «let err = db.exec("UPDATE ...", param...) in ...» тоже. Ну хорошо. Прочитал вот тут про монаду состояния. Автор сэмулировал ее в жабаскрипте. Меня удивило, что ничего особенно сложного (по крайней мере в этом типе монад) я не заметил. Возможно я что-то тотально не понял и мне только показалось, что все понятно. И вот я сделал аналогичный код на D для того же стека на базе массива. Можно ли считать, что я сделал аналог монады состояния или все же, что-то было глобально не понято? Функции push и pop каррированы вручную, хотя в D для это есть бибилиотечная функция. http://dpaste.dzfl.pl/bcf704330224 import std.stdio; auto push(int value) { return (const int[] stack) => stack ~ value; } auto pop() { return (const int[] stack) => stack.dup[0..$-1]; } auto monad(FS...)(FS funcs) if(funcs.length > 1) { return (const int[] stack) => monad(funcs[1..$])(funcs[0](stack)); } auto monad(FS...)(FS funcs) if(funcs.length == 1) { return (const int[] stack) => funcs[0](stack); } void main() { auto computation = monad( push(5), push(3), pop ); computation([1, 2]).writeln; } |
Сообщ.
#14
,
|
|
|
Смотри как бы у тебя не развился D головного мозга Все зачем-то на D переводишь. Это скорее вредно при попытках разобраться в чем-либо.
|
Сообщ.
#15
,
|
|
|
Цитата applegame @ 1) Да, но ведь такая функция получается не "чистая". 2) Ну хорошо. Прочитал вот тут про монаду состояния. Автор сэмулировал ее в жабаскрипте. Меня удивило, что ничего особенно сложного (по крайней мере в этом типе монад) я не заметил. Возможно я что-то тотально не понял и мне только показалось, что все понятно. И вот я сделал аналогичный код на D для того же стека на базе массива. Можно ли считать, что я сделал аналог монады состояния или все же, что-то было глобально не понято? Функции push и pop каррированы вручную, хотя в D для это есть бибилиотечная функция. http://dpaste.dzfl.pl/bcf704330224 import std.stdio; auto push(int value) { return (const int[] stack) => stack ~ value; } auto pop() { return (const int[] stack) => stack.dup[0..$-1]; } auto monad(FS...)(FS funcs) if(funcs.length > 1) { return (const int[] stack) => monad(funcs[1..$])(funcs[0](stack)); } auto monad(FS...)(FS funcs) if(funcs.length == 1) { return (const int[] stack) => funcs[0](stack); } void main() { auto computation = monad( push(5), push(3), pop ); computation([1, 2]).writeln; } 1) Она нечиста лишь потому, что нечиста БД, с точки зрения языка она относительно чиста, т.к. не позволяет изменять значения переменных. Ну в Хаскелле для того и существует IO, а в Эрланге с его динамической типизацией… Хз, возможно и можно было помечать все нечистые функции как-нибудь и сделать эту пометку «заразной», но зачем? Эрланг больше про взаимодействие процессов, чем функциональщину, а процессы выполняются параллельно, т.е. в любом случае получаем нечистую систему, просто описывается она языком в основном чистых функций. Так что Эрланг — далеко не самый удачный язык для знакомства с ФП, лучше взять Хаскелл, Clean, Miranda (последний, правда, давно мёртв). 2) Ты ничего не понял, я же написал, что Монада (в Хаскелле) — это просто интерфейс или абстрактный класс с парой методов (на самом деле там их вроде четыре, но обычно определяют два — return и (>>=), т.к. (=<<), (>>) и (<<) выражены через (>>=), а fail определяется автоматически или что-то в таком духе). Т.е. на «традиционном ООП языке» Монада выглядит так: // Monad lib public interface Monad forall<A, B> { Monad<B> bind(M<B> proc(A)); } // Monad IO lib import Monad; public class IO<A> : Monad forall<B> { private A value; // конструктор выполняет роль функции join (она же return в Хаскелльной Monad) public IO(A value) { this.value = value; } public IO<B> bind(IO<B> proc(A)) { return proc(this.value); } } // IO utilities lib import IO; public IO<Void> print(T value) { Console.WriteLine(value); return new IO<Void>(); } public IO<T> read() { return new IO<T>(Console.Read<T>()); } // Our code import IO, IOutil; Int inc(Int x) { return x + 1; } IO<Int> ioInc(Int x) { return new IO<Int>(x + 1); } Void main() { IO<Int> x = read<Int>(); // теперь мы не можем просто взять и вытащить x из монады IO // и не можем использовать простую inc, только ioInc x .bind(ioInc) .bind(print); // важно то, что результатом любой манипуляции с IO-значением // является (другое или такое же) IO-значение, т.е. // монада как бы "заразна". Вот и всё. } Это упрощённо, без ленивости. Добавлено Цитата applegame @ Автор сэмулировал ее в жабаскрипте. Совершенно, абсолютно бесполезное занятие, особенно для объяснения, что такое монада. Автор вообще не понял, что это, смешал в кучу монаду, ST и ленивость. Зачем? Монада IO в JS, да и в (почти) любом императивном языке — это точка с запятой ( ; ), точнее это функция bind, именно она позволяет компилятору выстроить правильную последовательность действий в программе. |