Здравствуйте, alex_public, Вы писали:
I>>Уже. Смотри внимательно пример про промисы. Там сходу сразу два действия паралельно.
_>Нет, там все вычисления в рамках монады идут строго последовательно.
Правильно. И это особенность не монады, а вычислений. Если для вычислений не нужны такие свойства, то и монады там никому не интересны.
Скажем, если ты делаешь операцию "перевести средства с одного счета на другой", то последовательные вычисления не имеют никакого отношения к монаде, это свойство самой задачи.
Отсюда ясно, что это свойство можно реализовать двумя способами
1. императивный код, в котором инструкции выполняются последовательно
2. монады, в которых операции выполняются последовательно
3. функции, в которых реализована конкретная последовательность вычислений
Еще пример задачи — покрасить автомобиль. Здесь четкая последовательность — зачистка, шпаклевка, шлифовка, грунтовка, покраска, полировка.
Вопрос — где здесь монады ?
I>>Нет, не представляю. Я вижу, что вызов get блокирует поток и вычисление приостанавливается. То есть, фактически эффект есть часть вычисления.
_>Ну так нам же об этом беспокоиться не надо, оно всё автоматом происходит где-то там... )
Ога.
I>>RAII это отделение некоторого контекста, а не эффекта. Контекст — стратегия инициализации, область видимости, счетчик ссылок и тд и тд. I>>Если ты переживаешь, что это без всяких монадо, то я тебя обрадую — это действительно не монады, это ко-монады.
_>Без строгих формул это всё слишком эфемерные понятия.
Открой теорию категорий да посмотри, там все в самом строгом виде, строже некуда.
Re[94]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Ты похоже совсем не понял о чём речь. )
_>1. Про декларативный js — это была ирония. )))
А я тебе сказал, что ирония не уместна.
_>2. А вот то, что Хаскель у нас декларативный, вызывает большие проблемы для него в uml. Только здесь уже речь шла не о диаграмме классов, а о других важнейших диаграммах (это всё обсуждалось где-то выше).
Нисколько. Я вот смотрю в wxHaskell и не вижу что бы твои слова подтверждались. Т.е. декларативность нисколько не мешает хаскелю в случае с ООП
Re[97]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Покажи как ты собираешься освобождать памятью.
Так по разному, зависит от конкретной задачи. Вот например у меня тут в одном реальном приложение изначально выделяется большой кусок памяти и используется всё время работы приложения — тут можно и вообще не удалять.
Но я не очень понял как это всё относится к вопросу использования иммутабельных данных. Это же вообще ортогональные вещи. Можно же использовать:
— иммутабельные данные через gc
— мутабельные данные через gc
— иммутабельные данные с ручным выделением памяти
— мутабельные данные с ручным выделением памяти
— иммутабельные данные через подсчёт ссылок
— мутабельные данные через подсчёт ссылок
— иммутабельные данные на стеке
— мутабельные данные на стеке
— иммутабельные данные на пуле
— мутабельные данные на пуле
....
Re[16]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Правильно. И это особенность не монады, а вычислений. Если для вычислений не нужны такие свойства, то и монады там никому не интересны.
Воот, наконец то ты всё правильно сформулировал. Так вот как раз из этого и следует моя основная мысль, что монады задают только подмножество императивного кода. Соответственно, если мы используем их только для подходящих задач, то всё отлично. А вот если будем пытаться задавать всё через них (типа как в декларативных языках, где других вариантов нет), то будем себя серьёзно ограничивать.
I>Открой теорию категорий да посмотри, там все в самом строгом виде, строже некуда.
Угу, только там нет ни "эффектов", ни "контекстов"... Да и вообще это не имеет отношения к программному коду. Нужна интерпретация... Вот для монад я тебе показывал нормальные практические определения, хотя знаю и математическое. А для ко-монад ты можешь что-нибудь практическое показать? )
Re[95]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Нисколько. Я вот смотрю в wxHaskell и не вижу что бы твои слова подтверждались. Т.е. декларативность нисколько не мешает хаскелю в случае с ООП
Во-первых, декларативность мешает не ООП, а использованию диаграмм действий и последовательностей (которые вместе с диаграммой классов являются основными в uml).
А во-вторых, ты действительно считаешь, что в Хаскеле есть ООП? ) Klapaucius наверное будет шокирован (для него же ООП — зло)... )))
Re[98]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Ikemefula, Вы писали:
I>>Покажи как ты собираешься освобождать памятью.
_>Так по разному, зависит от конкретной задачи. Вот например у меня тут в одном реальном приложение изначально выделяется большой кусок памяти и используется всё время работы приложения — тут можно и вообще не удалять.
_>Но я не очень понял
Покажи как ты собираешься освобождать память. Не надо никаких слов, просто кусочек кода — upward funarg, замыкание , move semantic и освобождение памяти.
Re[96]: Есть ли вещи, которые вы прницпиально не понимаете...
I>>Нисколько. Я вот смотрю в wxHaskell и не вижу что бы твои слова подтверждались. Т.е. декларативность нисколько не мешает хаскелю в случае с ООП
_>Во-первых, декларативность мешает не ООП,
Правильно. Более того — она вообще не мешает ООП.
>а использованию диаграмм действий и последовательностей (которые вместе с диаграммой классов являются основными в uml).
А раз не мешает, то стало быть нет никаких проблем по диаграмме классов накидать код.
_>А во-вторых, ты действительно считаешь, что в Хаскеле есть ООП? ) Klapaucius наверное будет шокирован (для него же ООП — зло)... )))
В хаскеле ООП реализуется на уровне библиотеки. Странно, да ? А тебе не кажется странным, что на уровне библиотеки оно поддерживается не только в языке Си (без плюсов), но и ассемблере ?
Re[99]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Покажи как ты собираешься освобождать память. Не надо никаких слов, просто кусочек кода — upward funarg, замыкание , move semantic и освобождение памяти.
Ты не спутал темки? ) Здесь мы говорим про иммутабельные данные, а не про замыкания без gc. Про замыкания без gc у нас разговор в темке про Swift. Но для меня не напряжно показать и здесь... Только не думай, что я при этом забуду про тему иммутабельных данных — ты так и не показал какие у них могут быть проблемы в следствие отсутствия gc.
auto MakeF()
{
int x=42;
return [=]{return x};//здесь выделяется память для int'a
}
{
auto f=MakeF();
f();
}//здесь память будет освобождена
Re[100]: Есть ли вещи, которые вы прницпиально не понимаете...
_>Ты не спутал темки? ) Здесь мы говорим про иммутабельные данные, а не про замыкания без gc. Про замыкания без gc у нас разговор в темке про Swift. Но для меня не напряжно показать и здесь... Только не думай, что я при этом забуду про тему иммутабельных данных — ты так и не показал какие у них могут быть проблемы в следствие отсутствия gc.
Представь себе что замыкания иммутабельные.
_>
_>auto MakeF()
_>{
_> int x=42;
_> return [=]{return x};//здесь выделяется память для int'a
_>}
_>{
_> auto f=MakeF();
_> f();
_>}//здесь память будет освобождена
_>
То есть, для всех иммутабельных данных ты предлагаешь расходовать стек ? Придется передавать их по значению и тд и тд.
Ты точно уверен, что получишь перформанс ?
Re[97]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>А раз не мешает, то стало быть нет никаких проблем по диаграмме классов накидать код.
Ну давай, расскажи, кто на твой взгляд будет единицей инкапсуляции в Хаскеле. С этим даже Klapaucius никак справиться не может. Посмотрим что ты скажешь...
I>В хаскеле ООП реализуется на уровне библиотеки. Странно, да ? А тебе не кажется странным, что на уровне библиотеки оно поддерживается не только в языке Си (без плюсов), но и ассемблере ?
И как у нас там реализовано наследование? )
Re[101]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>Представь себе что замыкания иммутабельные.
Вообще то они именно такие и есть по умолчанию. Чтобы сделать мутабельными, надо добавить специальный модификатор.
I>То есть, для всех иммутабельных данных ты предлагаешь расходовать стек ? Придется передавать их по значению и тд и тд.
I>Ты точно уверен, что получишь перформанс ?
Если вместо инта был бы vector<int>(1000000000), то у нас действительно была бы проблемка... До появления move semantics её решали с помощью всяческих shared_ptr и т.п. Тоже вполне себе решение, но не идеальное. А вот с move semantics мы получим поведение полностью как в примере с int'ом и при этом будет копирование всего лишь sizeof(vector<Т>), т.е. жалкие 12 байт (на 32 битной машине)...
Re[98]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>А раз не мешает, то стало быть нет никаких проблем по диаграмме классов накидать код.
_>Ну давай, расскажи, кто на твой взгляд будет единицей инкапсуляции в Хаскеле. С этим даже Klapaucius никак справиться не может. Посмотрим что ты скажешь...
Я не знаю что ты понимаешь под инкапсуляцией. Судя по твоим ответам это чтото навроде игры в пермишны.
На уровне библиотеки это можно сделать бесконечным количеством способов. В любом языке. За доказательством смотри полноту по тьюрингу.
Можно, скажем, хоть акторы реализовать.
Re[102]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>Ты точно уверен, что получишь перформанс ?
_>Если вместо инта был бы vector<int>(1000000000), то у нас действительно была бы проблемка... До появления move semantics её решали с помощью всяческих shared_ptr и т.п. Тоже вполне себе решение, но не идеальное. А вот с move semantics мы получим поведение полностью как в примере с int'ом и при этом будет копирование всего лишь sizeof(vector<Т>), т.е. жалкие 12 байт (на 32 битной машине)...
То есть, все иммутабельные объекты независимо от кода это 12 байт ? Правильно я тебя понял ?
А что если я захвачу 10 гуидов ? А если другой иммутабельный объект, что как бы типичный случай ? А если таких объектов будет целая цепочка, чего делать ?
Re[98]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>А раз не мешает, то стало быть нет никаких проблем по диаграмме классов накидать код.
_>Ну давай, расскажи, кто на твой взгляд будет единицей инкапсуляции в Хаскеле. С этим даже Klapaucius никак справиться не может. Посмотрим что ты скажешь...
Здравствуйте, Ikemefula, Вы писали:
I>Я не знаю что ты понимаешь под инкапсуляцией. Судя по твоим ответам это чтото навроде игры в пермишны.
Инкапсуляция очевидно должна осуществлять замыкание некого набора данных (и таких однотипных кусков может быть много) и кода, работающего с этими данными. Так вот у меня был вопрос в какую сущность инкапсулируются данные в Хаскеле... В ООП этой сущностью является собственно объект.
I>На уровне библиотеки это можно сделать бесконечным количеством способов. В любом языке. За доказательством смотри полноту по тьюрингу.
Нельзя. Т.е. можно, если мы говорим о наследование времени исполнения (своеобразной разновидностью композиции). Но это совсем не эффективно по сравнению с нормальным наследованием времени компиляции. Вот его на библиотеках не реализуешь. Естественно если речь не о чём-то типа библиотеки крутых макросов позволяющих мощное метапрограммирование.
I>Можно, скажем, хоть акторы реализовать.
Акторы по идее и не требуют ничего интересного во время компиляции...
Re[103]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, Ikemefula, Вы писали:
I>То есть, все иммутабельные объекты независимо от кода это 12 байт ? Правильно я тебя понял ?
Значит смотри, в C++ принято:
1. Использовать объекты на стеке. При этом у них обычно определены все соответствующие операторы, так что работа выглядит полностью как с каким-нибудь int'ом.
2. Если объект большого объёма, то он хранит данные в куче (а может и вообще быть какой-нибудь VirtualAlloc ), а за выделение/удаление этой памяти отвечает конструктор/деструктор этого объекта. сам же объект при этом по прежнему живёт на стеке и занимает при этом вообще каплю памяти.
3. Объекты можно передавать как по ссылке, так и по значению. И если для мелких объектов разницы особой нет, то для крупных передача по значению не эффективна (т.к. оператор копирования, копирует и ту динамическую память).
4. Однако возврат из функции ссылки на объект из стека этой функции не может работать. Поэтому имеем проблему, причём не только для замыканий, а вообще по эффективному возврату значения из функции. Т.е. надо или выделять возвращаемый объект в куче и возвращать ссылку на него или же терпеть неэффективный (и главное не нужный тут на самом деле) оператор копирования или же (эффективный, но не всегда уместный вариант и как раз для замыканий не подходящий) передавать в функцию ссылку на внешний объект, в качестве параметра.
5. Появление move semantics позволяет для всех подобных случаев заменить неэффективный оператор копирования на практически мгновенный оператор перемещения, тем самым полностью решая проблему.
Причём всё вышеперечисленное никак не зависит от того иммутабельные у нас данные или же нет. И я собственно так и не понял к чему ты обсуждаешь этот вопрос в теме про использование иммутабельных данных.
I>А что если я захвачу 10 гуидов ? А если другой иммутабельный объект, что как бы типичный случай ? А если таких объектов будет целая цепочка, чего делать ?
Кстати, насчёт мелких объектов... Советую глянуть в реализацию std::string — там обычно есть любопытная оптимизация для мелкий строк. )
Re[99]: Есть ли вещи, которые вы прницпиально не понимаете...
Не вижу по ссылке ни одного слова ни про комонады, ни про инкапсуляцию. Вижу только классы типов, которые являются аналогом скорее уж интерфейсов из ООП.
Re[100]: Есть ли вещи, которые вы прницпиально не понимаете...
1.3 Hiding implementation details: use module export list
One more usage of OOP classes is to hide implementation details, making internal data/functions inaccessible to class clients. Unfortunately, this functionality is not part of type class facilities. Instead, you should use the sole Haskell method of encapsulation, module export list:
module Stack (Stack, empty, push, pop, top, isEmpty) where
newtype Stack a = Stk [a]
empty = Stk []
push x (Stk xs) = Stk (x:xs)
pop (Stk (x:xs)) = Stk xs
top (Stk (x:xs)) = x
isEmpty (Stk xs) = null xs
Since the constructor for the data type Stack is hidden (the export list would say Stack(Stk) if it were exposed), outside of this module a stack can only be built from operations empty, push and pop, and examined with top and isEmpty.
Re[5]: Есть ли вещи, которые вы прницпиально не понимаете...
Кстати, вот еще вопросы
1 в самом Хаскеле монады — это конструкция языка ("встроенная в компилятор") или что-то, построенное на основе других средств языка? Если последнее, то интересно как удается достичь соответствующего эффекта?
2 какие вообще бывают монады? Хочется как можно более полный список.
Re[100]: Есть ли вещи, которые вы прницпиально не понимаете...
Здравствуйте, alex_public, Вы писали:
I>>Я не знаю что ты понимаешь под инкапсуляцией. Судя по твоим ответам это чтото навроде игры в пермишны.
_>Инкапсуляция очевидно должна осуществлять замыкание некого набора данных (и таких однотипных кусков может быть много) и кода, работающего с этими данными. Так вот у меня был вопрос в какую сущность инкапсулируются данные в Хаскеле... В ООП этой сущностью является собственно объект.
Это очень странное определение инкапсуляции. Как будет устроен объект ООП ни разу специфицирует. Главное, что нужно обеспечить, это идентити. Т.е. нужна возможность послать сообщение конкретному объекту. А где и как этот объект будет хранить данные — дело десятое. Важно, что бы разные объекты могли работать со своими данными.
I>>На уровне библиотеки это можно сделать бесконечным количеством способов. В любом языке. За доказательством смотри полноту по тьюрингу.
_>Нельзя.
то есть, ты утверждаешь, что хаскель не обладает полнотой по тьюрингу ? Вот так новость.
?Т.е. можно, если мы говорим о наследование времени исполнения (своеобразной разновидностью композиции). Но это совсем не эффективно по сравнению с нормальным наследованием времени компиляции. Вот его на библиотеках не реализуешь. Естественно если речь не о чём-то типа библиотеки крутых макросов позволяющих мощное метапрограммирование.
Ты вероятно под ООП понимаешь исключительно вариант "инкапсуляция-наследование-полиморфизм как в С++". Между тем это всего лишь симуловское ООП, которое реализовано в С++. Скажем, Алан Кей, изобретатель ООП, c таким вариантом не согласен.
I>>Можно, скажем, хоть акторы реализовать.
_>Акторы по идее и не требуют ничего интересного во время компиляции...
У тебя есть сомнения, что на акторах реализуется ООП ?