Re[44]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 09.02.14 16:25
Оценка: +1
Здравствуйте, Ikemefula, Вы писали:

I>Любой ФЯ намного ближе к математике чем С++ а следовательно и уровнем выше.


С чего это "следовательно"? ) Я же сказал, что близость к математике не означает ещё ничего.

I>В С++ такая вещь, как композиция функций, это много-много ручной работы, вагоны темплейтов распиханых по разным уголкам, а в ФЯ это все одной строчкой.


А в ФЯ другие вещи требуют много-много ручной работы, в то время как в C++ делаются одной строкой. Я же говорю, ФЯ — это не уровень, а просто другой взгляд. И он тоже может быть разных уровней.
Re[47]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 09.02.14 16:33
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Ты на нем не пишешь в продакшн Судя по тем вещам, которые ты выдал в разговоре про монады, короутины и async/await ты яростно защищает императивные фичи.


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

I>Дальше можно не читать, потому что ты съехал на субъективные вещи. Я вот тоже самое могу сказать про С++, в ём два языка — один обычный, наследник С++, а другой мутный, запутаный и неудобный язык шаблонов.


Это не субъективные вещи, а вполне очевидные. Про которые пишут даже специалисты по Хаскелю в учебниках.

I>Я хаскель разбираю в основном по таким вот примерам и пока что ни разу не ужаснулся. Нужно всего то разделять UI и логику приложения, IO и обработку данных.


Разделять то надо. Но при этом не обязательно в разных частях использовать "разные языки". )
Re[48]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.02.14 17:05
Оценка:
Здравствуйте, alex_public, Вы писали:

I>>Ты на нем не пишешь в продакшн Судя по тем вещам, которые ты выдал в разговоре про монады, короутины и async/await ты яростно защищает императивные фичи.


_>Монады, короутины и async/await не имеет никакого отношения к функциональщине. Ну разве что для монад ещё требуется некий минимум типа первоклассных функций, но это есть в очень многих языках.


А я про то, как ты защищаешь императивные фичи.

I>>Дальше можно не читать, потому что ты съехал на субъективные вещи. Я вот тоже самое могу сказать про С++, в ём два языка — один обычный, наследник С++, а другой мутный, запутаный и неудобный язык шаблонов.


_>Это не субъективные вещи, а вполне очевидные. Про которые пишут даже специалисты по Хаскелю в учебниках.


Удобство стало очевидной вещью ? Чудеса. Ни разу не видел, что бы специалист по Хаскелю сказал, что Хаскель неудобен. Ссылку дашь ?

_>Разделять то надо. Но при этом не обязательно в разных частях использовать "разные языки". )


Правильно, не обязательно, а ты вещаешь как будто тебя силой заставляют. А вот в С++, кстати говоря, без "разных языков" вообще ничего внятного не делается. Более того, С++ это скорее три языка, а не два, с учетом того, что шаблоны включают в себя метапрограммирование.
Re[45]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.02.14 17:12
Оценка:
Здравствуйте, alex_public, Вы писали:

I>>Любой ФЯ намного ближе к математике чем С++ а следовательно и уровнем выше.


_>С чего это "следовательно"? ) Я же сказал, что близость к математике не означает ещё ничего.


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

I>>В С++ такая вещь, как композиция функций, это много-много ручной работы, вагоны темплейтов распиханых по разным уголкам, а в ФЯ это все одной строчкой.


_>А в ФЯ другие вещи требуют много-много ручной работы, в то время как в C++ делаются одной строкой. Я же говорю, ФЯ — это не уровень, а просто другой взгляд. И он тоже может быть разных уровней.


ФЯ это прежде всего уровень, близость к математике.
Вот, смотри — здесь нет никакого "другого" взгляда, здесь практически формула из учебника математики
f(1) -> 1
f(2) -> 1
f(N) -> f(N-1) + f(N-2)


"Другой" взгляд появится, когда ты перепишешь это в итерационном виде.
Re[49]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 09.02.14 20:41
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Удобство стало очевидной вещью ? Чудеса. Ни разу не видел, что бы специалист по Хаскелю сказал, что Хаскель неудобен. Ссылку дашь ?


Уже кидал одну из ссылок прямо в этой темке. И там естественно речь шла не вообще про Хаскель, а про монадную (подразумевая IO/ST) разновидность.
Re[50]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 09.02.14 20:45
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Уже кидал одну из ссылок прямо в этой темке. И там естественно речь шла не вообще про Хаскель, а про монадную (подразумевая IO/ST) разновидность.


На самом деле не важно, удобство непроверяемо и нефальсифицируемо
Re[46]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 09.02.14 20:55
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Близость к математике это абстрации, это и есть уровень языка. Если ты не согласен, то дай внятное определение, что же такое уровень языка


Абстракции — это да. Но причём тут математика? )

Кстати, вот лично у меня как раз по математике образование высшего академического уровня (и совсем не с программерской стороны, а пофундаментальнее), но я не вижу там ничего такого особо высокоуровневого в смысле абстракций. Абстракции как-то больше в философии или в той же самой архитектуре ПО встречаются. )

I>ФЯ это прежде всего уровень, близость к математике.

I>Вот, смотри — здесь нет никакого "другого" взгляда, здесь практически формула из учебника математики
I>
I>f(1) -> 1
I>f(2) -> 1
I>f(N) -> f(N-1) + f(N-2)
I>


I>"Другой" взгляд появится, когда ты перепишешь это в итерационном виде.


Ну да, ФЯ — это близость к математике. Но причём тут уровень языка? )

И кстати ты тут просто приводишь пример подходящий как раз под ФЯ. А можно наоборот накидать кучу примеров, которые будут выглядеть очевидно в императивном виде и очень сложно выражаться в ФЯ.
Re[46]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 10.02.14 05:05
Оценка:
Здравствуйте, Ikemefula, Вы писали:

Кстати, вот http://habrahabr.ru/post/211871/ сегодня вышла статья очень в тему... Она как раз про то, что на мой взгляд является высокоуровневыми вопросами. И как видно, пока что у ФП дела с этим обстоят довольно мрачно.
Re[47]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.02.14 06:53
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Кстати, вот http://habrahabr.ru/post/211871/ сегодня вышла статья очень в тему... Она как раз про то, что на мой взгляд является высокоуровневыми вопросами. И как видно, пока что у ФП дела с этим обстоят довольно мрачно.


Я шота не вижу там определения. Там говорится "низкий дизайн" в контексте Хаскеля или ФЯ, а не в сравнении с ассемблером. Этот низкий уровень Хаскеля намного выше как ассемблера, так и с++.

И ежу понятно, что в каждом языке будут некоторые базовые конструкции которые и определяют низкий уровень на этом языке. Но при этом низкий уровень Хаскеля вообще никак не соотносится с железом. Скажем с С++ ровно наоборот — низкоуровневые конструкции запилены под архитектуру современных микропроцессоров.
Re[47]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.02.14 07:02
Оценка:
Здравствуйте, alex_public, Вы писали:
I>>Близость к математике это абстрации, это и есть уровень языка. Если ты не согласен, то дай внятное определение, что же такое уровень языка

_>Абстракции — это да. Но причём тут математика? )


При том, что математика это абстрации в чистом виде, еще чище чем в Хаскеле.

_>Кстати, вот лично у меня как раз по математике образование высшего академического уровня (и совсем не с программерской стороны, а пофундаментальнее), но я не вижу там ничего такого особо высокоуровневого в смысле абстракций. Абстракции как-то больше в философии или в той же самой архитектуре ПО встречаются. )


Я честно говоря не знаю, что ты понимаешь под словом абстракция

I>>"Другой" взгляд появится, когда ты перепишешь это в итерационном виде.


_>Ну да, ФЯ — это близость к математике. Но причём тут уровень языка? )


При том, что есть всего два полюса — железо и специфичная область математики. Одно принято считать низким уровнем, а другое — высоким.

_>И кстати ты тут просто приводишь пример подходящий как раз под ФЯ. А можно наоборот накидать кучу примеров, которые будут выглядеть очевидно в императивном виде и очень сложно выражаться в ФЯ.


Можно накидать сотню строчек на ассемблере и может оказаться так, что для этого клочка нет и не может быть ниодной аналитической модели, что с того ? Это всё равно будет низкий уровень.
Re: Есть ли вещи, которые вы прницпиально не понимаете...
От: Rinbe Россия  
Дата: 10.02.14 10:15
Оценка:
Здравствуйте, Greeter, Вы писали:

G>Или не до конца понимаете в программировании? Для меня вот например Oracle это что-то типа пятого измерения В теории какбы понятно — деревья, логарифмические алгоритмы, интерпретаторы с перкомпиляцией, кэши разные. Но как оно все вместе так хитро собрано, и почему оно такое пц быстрое, и при этом устойчивое, и как работает его оптимизатор? Вообще не представляю.


Принципы пакетирования, я их понимаю, но в "полном объеме" ни когда ими не пользовался.
Re[36]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Klapaucius  
Дата: 10.02.14 11:21
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>
EP>quicksort :: Ord a => [a] -> [a]
EP>quicksort []     = []
EP>quicksort (p:xs) = (quicksort lesser) ++ [p] ++ (quicksort greater)
EP>    where
EP>        lesser  = filter (< p) xs
EP>        greater = filter (>= p) xs
EP>


EP>Это никакой не Tree Sort, это именно пародия на quick sort.


Не понятно, какой смысл вы вкладываете в слова "пародия на quick sort", но это совершенно точно tree sort. Называть это quicksort, конечно, неправильно.
То, что это tree sort в глаза сразу не бросается потому, что он дефористирован вручную. Т.е. функция построения дерева (несбалансированного)
data Tree a = Leaf | Node (Tree a) a (Tree a)

toTree [] = Leaf
toTree (p:xs) = Node (toTree lesser) p (toTree greater) where
        lesser = filter (< p) xs
        greater = filter (>= p) xs

и "сплющивания" дерева
toList Leaf = []
toList (Node l x r) = toList l ++ [x] ++ toList r

просто "сфьюжены" вручную.

EP>Quick Sort делит массив на две части (вырезая середину), и продолжает рекурсивно в каждой из частей. Начиная с определённой глубины текущий Range полностью поместится в L3, ещё глубже — L2, потом в L1 и так далее.


Ну, не каждый divide-and-conquer алгоритм считается cache-oblivious. Почитайте про какой-нибудь funnel-sort там разница хорошо понятна. Да и как divide-and-conquer quick sort — не фонтан. Потому, что качество деления у него от данных зависит (во отличие от той же сортировки слияниями).
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[48]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 10.02.14 12:51
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>Я шота не вижу там определения. Там говорится "низкий дизайн" в контексте Хаскеля или ФЯ, а не в сравнении с ассемблером. Этот низкий уровень Хаскеля намного выше как ассемблера, так и с++.


I>И ежу понятно, что в каждом языке будут некоторые базовые конструкции которые и определяют низкий уровень на этом языке. Но при этом низкий уровень Хаскеля вообще никак не соотносится с железом. Скажем с С++ ровно наоборот — низкоуровневые конструкции запилены под архитектуру современных микропроцессоров.


Речь о другом. В этой статье обсуждаются действительно высокоуровневые вещи, определяющие архитектуру ПО. Для большинства языков (как императивных, так и функциональных) эти вещи не имеют прямого выражения в структурах языка, а существуют сами по себе. Так вот, если для императивных языков эта область имеет громадное количество готовых концепций, специализированных инструментов и т.п., то для функциональных автор сумел наскрести 1,5 известных концепции и 0 готовых инструментов. Собственно большую часть статьи автор и пытается придумать чем ему заменить в функциональном языке все эти известные и хорошо работающие вещи из мира императивных языков.

Т.е. если смотреть с самого верха, то программирование и на чистом C++ и на чистом Haskell'е весьма низкоуровневое. Однако, если под нашу конкретную задачу, существует готовый мощный фреймворк, то тогда программирование может резко стать очень высокоуровневым и на C++ и на Haskell'e. Хотя при таких раскладах это уже становится скорее программированием именно на этом фреймворке (как на неком неформализированном DSL). Т.е. в общем то ситуация равная, с поправкой на то, что для мира императивных языков подобных вещей существует на порядки больше и существуют специальные концепции и инструменты для их удобного построения.

Ну и есть языки, в которых данные вопросы решены уже на уровне самого языка. Это чаще всего всяческие специализированные DSL'и. Вот они и являются максимально высокоуровневыми, правда практически всегда это достигается резким сокращением универсальности.
Re[48]: Есть ли вещи, которые вы прницпиально не понимаете...
От: alex_public  
Дата: 10.02.14 12:59
Оценка:
Здравствуйте, Ikemefula, Вы писали:

I>При том, что математика это абстрации в чистом виде, еще чище чем в Хаскеле.


Математика безусловно использует абстракции везде. А вот обратное уже совсем не верно... )

I>Я честно говоря не знаю, что ты понимаешь под словом абстракция


Смотря в каком контексте. Но здесь речь шла о том, что математика не обязательно имеет к этому какое-то отношение.

Вот например, подскажи мне какой раздел математики позволит мне записать концепцию ООП в виде формул? )

I>При том, что есть всего два полюса — железо и специфичная область математики. Одно принято считать низким уровнем, а другое — высоким.


Это оно у тебя так принято. )))

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


Конечно низкий. Т.е. и это и задание математической функции в коде — это низкий уровень. )
Re[49]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.02.14 16:30
Оценка:
Здравствуйте, alex_public, Вы писали:

I>>При том, что математика это абстрации в чистом виде, еще чище чем в Хаскеле.


_>Математика безусловно использует абстракции везде. А вот обратное уже совсем не верно... )


Математика только абстракции и использует. В ней нет ничего конкретного. 2 + 2 — абстракции в чистом виде, во первых сами числа, во вторых — операция

I>>Я честно говоря не знаю, что ты понимаешь под словом абстракция


_>Смотря в каком контексте. Но здесь речь шла о том, что математика не обязательно имеет к этому какое-то отношение.


математика это язык описания абстракций

_>Вот например, подскажи мне какой раздел математики позволит мне записать концепцию ООП в виде формул? )


Открой для себя семантику программирования, это дисциплина которая занимается построением и изучением математических моделей для всех языковых конструкций. На каком именно базисе будет построено ООП, не в курсе

I>>При том, что есть всего два полюса — железо и специфичная область математики. Одно принято считать низким уровнем, а другое — высоким.


_>Это оно у тебя так принято. )))


Нет, не у меня, не угадал.

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


_>Конечно низкий. Т.е. и это и задание математической функции в коде — это низкий уровень. )


... а в Киеве дядька.
Re[49]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 10.02.14 16:36
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Речь о другом. В этой статье обсуждаются действительно высокоуровневые вещи, определяющие архитектуру ПО. Для большинства языков (как императивных, так и функциональных) эти вещи не имеют прямого выражения в структурах языка, а существуют сами по себе. Так вот, если для императивных языков эта область имеет громадное количество готовых концепций, специализированных инструментов и т.п., то для функциональных автор сумел наскрести 1,5 известных концепции и 0 готовых инструментов. Собственно большую часть статьи автор и пытается придумать чем ему заменить в функциональном языке все эти известные и хорошо работающие вещи из мира императивных языков.


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

_>Т.е. если смотреть с самого верха, то программирование и на чистом C++ и на чистом Haskell'е весьма низкоуровневое.


Из этого не следует, что у этих языков один и тот же уровень или хотя бы уровни близкие.

>Однако, если под нашу конкретную задачу, существует готовый мощный фреймворк, то тогда программирование может резко стать очень высокоуровневым и на C++ и на Haskell'e. Хотя при таких раскладах это уже становится скорее программированием именно на этом фреймворке (как на неком неформализированном DSL). Т.е. в общем то ситуация равная, с поправкой на то, что для мира императивных языков подобных вещей существует на порядки больше и существуют специальные концепции и инструменты для их удобного построения.


В общем случае если мы сделаем АПИ для этого фремворка в разных языках, внезапно, будет разница в том, что как эффективно использовать и где за каким деталями придется следить.
Вот в С++ ты точно не сможешь избавиться от указателей, инстанцирований, деклараций шаблонов, указания типов и тд и тд и тд
А в Хаскеле — запросто.

_>Ну и есть языки, в которых данные вопросы решены уже на уровне самого языка. Это чаще всего всяческие специализированные DSL'и. Вот они и являются максимально высокоуровневыми, правда практически всегда это достигается резким сокращением универсальности.


DSL как правило это небольшая, очень узкая область математики
Re[46]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.14 05:16
Оценка:
Здравствуйте, alex_public, Вы писали:

_>И так, появилась идея создать чистый функциональный язык. Для этого надо как-то решить проблему не вписывающихся в эту концепцию обязательных нюансов программирования. Как минимум это "изменение состояния" и ввод/вывод (тоже в общем то состояние, только как бы внешнего мира). В Хаскеле эту проблему решили с помощью выделения всего кода ST/IO в некую специальную резервацию. Кстати, построение резервации выполнено с помощью монадных техник (далеко не единственный вариант) и как раз исключительно это и является причиной такого широкого использования монад в Хаскеле (с этого моего утверждения и началась вся эта дискуссия). Так вот, в результате мы получили внутри Хаскеля ещё один маленький встроенный язык, причём уже чётко императивный. Естественно он убогонький и неудобный, причём не только по сравнению с самим Хаскелем, но и в сравнение с классическими императивными языками (что не удивительно, т.к. у в них именно такая функциональность оттачивалась годами). Но видимо авторы языка посчитали это приемлемой ценой за возможность писать вне этого подъязыка строго чистый и ленивый код.

Всё совершенно наоборот. Нет никаких "не вписывающихся в концепцию" нюансов; ФП с самого начала эквивалентно МТ (см. Тезис Чёрча).
ФП честно объясняет: у вас нет никакого "глобального вычислителя", который неявно передаётся от команды к команде. Если вам нужно состояние — то вы описываете его явно. Дело не в резервации, а в том, что выписывать руками нудную передачу состояния — лень. Поэтому внимательные ФП-шники заметили, что "результат функции" и "результат функции плюс состояние мира" можно описать абстрактно. А из любой чистой функции можно получить функцию, работающую с состоянием, путём применения той же техники, которая применима к функциям, работающим с "необязательными значениями". И эта техника — как раз монады. Всё.

Ваши рассуждения про резервацию должны бы быть применимы к любой другой монаде — например, к монаде List, или Optional. Но почему-то вам кажется, что IO/ST — это какая-то отдельная резервация, а Optional — это нормальный ФП код.

_>И для определённого вида приложений это действительно замечательно. Например, если мы возьмём приложение, которое считает что-то сложное и потом просто печатает это в консоль, то вся "нехорошая" часть приложения сведётся к виду "main=print $ pure_main", а вся остальная часть приложения будет представлять из себя красивый чистый и ленивый код. Красота!

Совершенно верно.

_>Однако если мы вернёмся из академического мира в реальность, то там ситуация становится противоположной. При написание скажем какого-нибудь десктопного GUI, наибольший объём кода у нас становится не в области нормального Хаскеля, а в области того самого убогого императивного подъязыка. Со всеми вытекающими из этого последствиями. И в итоге весь смысл изначальной идей оказывается выкинутым в помойку.

Странно. Весь "десктопный GUI" в современных системах — это реализация оконной функции. Совершенно непонятно, почему вы считаете эту функцию какой-то особенной. Просто она вызывается много раз за время жизни приложения, а не один, как функция main.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[49]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Sinclair Россия https://github.com/evilguest/
Дата: 11.02.14 05:19
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Вот например, подскажи мне какой раздел математики позволит мне записать концепцию ООП в виде формул? )

Computer Science.
См. https://www.google.ru/search?q=theory+of+classification+site:jot.fm Чистая математика, вся концепция ООП в виде формул.
Уйдемте отсюда, Румата! У вас слишком богатые погреба.
Re[36]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Klapaucius  
Дата: 11.02.14 09:25
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Ну так это же не ФЯ с его ограничениями на иммутабельность — мы можем создавать что угодно, не только возвращая значения из функций. )


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

_>Шаблоны проектирования прекрасно реализуются и без всякого МП, так что оно собственно тут ни при чём. Так вот, возвращаясь к шаблонам проектирования... Это разве на ваш взгляд не абстракции достаточно высокого уровня?


Нет, не реализуются. Без метапрограммирования никаких шаблонов проектирования в коде нет — только результат их применения в голове программиста. Поэтому к уровню кода они никакого значения не имеют.

_>Вот например возьмём такое общеизвестное простейшее приложение как "Блокнот". Из каких математических объектов он будет состоять, если мы его реализуем по высокоуровневому? )


Из функций, категорий, моноидов, функторов, монад и т.д.

_>Нуну)


_>Возьмём например такой простейший код, работающий через константные ссылки:

_>
_>prepare :: Array Int Int -> Array Int Int
_>prepare а = а//[(1, а!1*а!1)]

_>test :: Array Int Int -> Int
_>test а = let r=prepare а
_>        in sum $ elems r
 
_>main = print $ test $ listArray (0, length l -1) l
_>        where l= [1, 2, 3]
_>


Ну конечно, если брать какую-нибудь убогую библиотеку, да еще и специально писать ужасы — тогда конечно.
Вот как выглядит нормальный код, использующий нормальную библиотеку:

prepare a = a // [(1, a!1^2)]
   
test = V.sum . prepare

main = print . test . V.fromList $ [1..3::Int]


_>Его прямым аналогом на C++ будет что-то вроде:


Нет, прямой аналог этого кода на C++ написать нельзя, потому что системы контроля эффектов в нем нет.

_>
_>auto prepare(const vector<int>& a)
_>{
_>    vector<int> r=a;
_>    r[1]=r[1]*r[1];
_>    return r;
_>}

_>auto test(const vector<int>& a)
_>{
_>    auto r=prepare(a);
_>    return accumulate(r.cbegin(), r.cend(), 0);
_>}

_>int main(){cout<<test({1, 2, 3});}
_>


_>А теперь предположим, что нам захотелось переделать это под неконстантные ссылки. Кстати, вполне реальная задачка, если у нас массив не из 3-ёх элементов, а из 3*10^9. На C++ это станет выглядеть так:

_>
_>void prepare(vector<int>& a){a[1]=a[1]*a[1];}

_>auto test(vector<int>&& a)
_>{
_>    prepare(a);
_>    return accumulate(a.cbegin(), a.cend(), 0);
_>}

_>int main(){cout<<test({1, 2, 3});}
_>

_>Видно, что код практически не изменился по своей структуре, а стал только проще — просто стёрли лишнее.

Ну так потому что код один и тот же. Странно ожидать, что один и тот же код будет выглядеть по разному.

_>Ну и теперь полюбуемся, как будет выглядеть что-то подобное на Хаскеле:

_>
_>prepare :: STArray s Int Int -> ST s ()
_>prepare a = do
_>    x <- readArray a 1
_>    writeArray a 1 (x*x)

_>test :: STArray s Int Int -> ST s Int
_>test a = do
_>    prepare a
_>    l <- getElems a
_>    return $ sum l

_>main = print $ runST $ do
_>    let l=[1, 2, 3]
_>    a <- newListArray (0, length l -1) l :: ST s (STArray s Int Int)
_>    test a
_>


prepare a = do
    x <- M.read a 1
    M.write a 1 (x*x)
    return a

test a = fmap V.sum (V.unsafeFreeze =<< prepare a)

main = print =<< test =<< (V.thaw . V.fromList $ [1..3::Int])


Что характерно, этот код отличается по скорости от первого моего примера на ~10% (если вектора взять по 100M элементов и преобразовывать не из списка, иначе измеряемое различие вообще не получить), т.е в "наивном" коде не убрано оптимизатором одно единственное лишнее копирование вектора.

_>И это ещё в лучше случае, если getElems в реальности создаёт ссылку, а не выделяет память (я просто не в курсе таких тонкостей). А если getElems выделяет память, то её использовать нельзя и придётся ещё самим писать новую версию sum, которая умеет работать с типом STArray s Int Int.


Вообще говоря, преобразовывать в список ленивый образом, "без копирования" небезопасно. Список можно проходить частями и никто не гарантирует, что изменяемый массив за это время не поменяется. Собственно поэтому в моем коде unsafeFreeze — я-то знаю, что собираюсь потребить все данные прямо тут, в функции sum, а компилятор нет. Именно этим копированием второй вариант от наивной реализации и отличается — если вместо unsafeFreeze написать freeze при преобразовании добавится копирование и разницы между вариантами не будет. Конечно, плохо, что для мутабельных массивов нет такого же богатого набора функций как и для иммутабельных, но это библиотечная проблема.

_>Но даже если забыть про этот момент, то в целом видно, что изначальный хаскельный код при переходе к монадному (который необходим для существования неконстантных ссылок) изменился до неузнаваемости.


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

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


Конечно он стал страшнее, по сравнению с "наивной" версией. Но не страшнее плюсовой, синтаксический мусор в которой существует вовсе без всякого смысла и оправдания.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Re[40]: Есть ли вещи, которые вы прницпиально не понимаете...
От: Klapaucius  
Дата: 11.02.14 10:18
Оценка:
Здравствуйте, alex_public, Вы писали:

_>Что-то я не понял, что вы тут хотели сказать. Что описываемую задачку можно решить без монадного кода? ) Если можно, то тогда с удовольствием посмотрю на это... Если же нельзя, то тогда в чём претензии к моим комментариям? )


Вы же сами сказали, что вам нужно получать в итоге переписывание вектора по месту. Значит по крайней мере одна функция-примитив с "монадным кодом" будет, хотя использовать ее в коде, использующем библиотеку не обязательно. Или это из моего объяснения было непонятно? Пользователю библиотеки доступен набор функций из иммутабельного массива в иммутабельный массив, реализованные через другие функции из иммутабельного массива в иммутабельный массив, а где-то в основании всего этого — пара-тройка примитивов, которые работают с мутабельными массивами и переписывают их по месту и которые автору библиотеки нужно написать. Из ниоткуда "монадный код" не возьмется, компилятор его сам не выдумает.

_>Если же нельзя, то тогда в чём претензии к моим комментариям? )


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

_>А что, без этих "лишних копирований" можно обойтись что ли? ) Как мы без них получим нормальные (не монадные) хаскельные функции? )


Никак бы не получили. Ну так эти копирования по условию задачи и нужно устранять. Они и устраняются. И не в ручную, а автоматически. Я это продемонстрировал. И где тут была ручная оптимизация?

_>Ну так мало ли откуда там идёт тот внешний буфер — далеко не факт, что он прямой результат new. А если делать дополнительную обёртку, то всё равно получим то самое копирование.


Захотим получим, не захотим — не получим. Все зависит от того, какие мы захотим иметь гарантии по безопасности.

_>Кстати, в реальности (изначальная задачка то из вполне реальной области была) там это выглядит так: первичный буфер предоставляет ОС, вызывая наш код 30 раз в секунду и передавая нам при этом указатель. Так вот на C++ естественно без проблем делается такая обработка вообще без выделения памяти — и внутри обработки одного кадра (про что и был код выше) и между кадрами. А как тут у Хаскеля дела? )


Вот так:
unsafeFromForeignPtr0 fp n = Vector n fp

т.е. Storable.Vector это просто структура, хранящая длину и указатель, который откуда угодно можно получать. Никакого копирования при этом не происходит.
'You may call it "nonsense" if you like, but I'VE heard nonsense, compared with which that would be as sensible as a dictionary!' (c) Lewis Carroll
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.