LINUX.ORG.RU

Функциональная парадигма

 , ,


2

7

Что-то в последнее время начали хайпить функциональное программирование. Мол, стиль со взглядом в будущее, распараллеливание, оптимизация, замена устаревшему ООП, который не способен идти в ногу с современными процессорами. Есть ли здесь люди, которые пишут на Haskell или тому подобных языках? Есть ли профит переходить на ФП? Или мультипарадигмость С++ и Java исправят ситуацию?


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

Это же идеоматический код. На хаскеле не надо писать идеоматический код?

Мне кажется, ты понимаешь что-то свое под словом «идИоматический». Этот код для хаскеля где-то как попытка решить эту же задачу на с++ в функциональном стиле.

Достаточно логично что?

Обозначение логичное.

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

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

С тем же успехом можно придраться к c++, почему там деструкторы обозначаются тильдой, а не как-нибудь в стиле:

destructor ClassName();

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

Не знаю, существуют ли гайдлайны на этот счет где-то в явном виде.

а не какой-то фигней, которую надо угадывать самому (мало того что читать нечитабельный хаскикод - еще и при помочи уличной телепатии определять, о чем подумал кретин-автор).

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

В-третьих, объясни все же, своими словами, пожалуйста - что означает «_» в конце ф-и, где тут логика (почему _ а не '? потому что ' занят? а чего не ^? или %? почему суффикс, а не префикс? почему он nonalphanumeric?), и что, кроме полной профнепригодности человека, писавшего код, мешало дать ф-и человеческий нейминг?

Если очень грубо и в термина Си, то функции с _ в конце не возвращают значение. То есть для foldM_ нас не интересует результат свертки, например.

Ну, сделали бы префикс, ты бы спросил, а почему не суфикс.

И да, в данном случае такие короткие названия функций удобнее.

Именно так, кстати, и делают 90% хаскелистов - исполняют некий набор «рекомендаций», имеющих сугубо магический характер (т.к. причин этих рекомендаций, т.е. откуда они берутся, данные деятели не знают), а потом оказывается, что посчитать среднее списка, не выжрав всю имеющуюся память и не гугля мануалы, может тот самый один из десяти. Потом метод расчета среднего списков добавляется в «рекомендации», но немного модифицируй задачу - и 90% вновь обосрутся.

Откуда у тебя такая богатая статистика по хаскелистам? =)

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

Ха! Так ты не понимаешь проблему того кода с вычислением среднего. Там вопрос, как посчитать среднее арифметическое списка, не создавая список в памяти. В большинстве других языков для этого понадобятся те еще пляски с бубном.

Многие проблемы с ленивостью хаскеля решаются расставлением bang patterns в объявлении типа. И контрол-флоу для этого в голове держать не обязательно.

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

Если под «подготовкой» подразумевается твердое знание синтаксиса и семантики языка - то такой «подготовки» достаточно вполне для понимания большинства языков с сиподобным синтаксисом, и совершенно недостаточно для понимания хаскеля.

Что тебе может помешать пониманию хаскеля, если ты знаешь его синтаксис и семантику? =)

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

А дать функции нормальное имя один раз и навсегда, в чем проблема? Ах, да, ведь синтаксис хаскеля - дерьмо и становится абсолютно нечитаем с длинными именами!

Нет, с длинными именами типа foldMonadWithNoReturn и foldLeftStrict было бы вполне удобно. С короткими удобнее.

По-этому все вынуждены рожать code smell с кавычками, подчеркиваниями и однобуквенными неймингами.

Нет там однобуквенного нейминга. Твои придирки нелепы. Нет при изучении хаскеля проблем с foldl/foldl'. Есть другие проблемы, но ты же не соизволил почитать учебник.

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

Этот код для хаскеля где-то как попытка решить эту же задачу на с++ в функциональном стиле.

А можно тогда увидеть идиоматический код решения той же задачи на хаскеле (эмуляция мутабельного состояния)? Ну может будет не ST/STRef, а какие-то другие вещи, но им эквивалентные получатся. В итоге почти тот же код. С чего же он неидиоматический если подругому не напишешь никак?

Обозначение логичное.

Я все еще жду пояснения этой логики. Почему _? И что он все-таки обозначает? И гден с этой логикой можно ознакомиться? Можно ли быть уверенным что нигде и никто не использует данный суффикс (как и ', например) в других контекстах?

Не путай функции какой-нибудь библиотеки отрисовывания кнопочек с относительно базовыми конструкциями языка.
С тем же успехом можно придраться к c++, почему там деструкторы обозначаются тильдой, а не как-нибудь в стиле:

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

Не знаю, существуют ли гайдлайны на этот счет где-то в явном виде.

Не имеются.

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

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

Ну, сделали бы префикс, ты бы спросил, а почему не суфикс.

Ты, вроде, говорил, что там какая-то логика. Если есть логика - значит, можно указать причину, почему выбран такой способ, а не какой-то иной. А тут «просто наугад взяли» - это логика?

Если очень грубо и в термина Си, то функции с _ в конце не возвращают значение. То есть для foldM_ нас не интересует результат свертки, например.

Давай без «грубо», давай как есть, четко и ясно. Представь, что тебе пм сказал добавить раздел для неймингов в ваш гайдлайн. Что ты там напишешь? Кукареканье про «функция какбы не возвращает значения, что-то там интересует или нет блаблабла»? Сразу, конечно, тут еще будут вопросы - а есть ли другие ф-и, которые тоже подходят под такое вот «не интересует значение», но при этом без _? А используется ли _ где-нибудь в других контекстах, обозначая то же самое (офк речь не об исключительных ситуациях, которых 3.5 штуки, их можно и проигнорить)?

И да, в данном случае такие короткие названия функций удобнее.

Нет, не удобнее.

Ха! Так ты не понимаешь проблему того кода с вычислением среднего. Там вопрос, как посчитать среднее арифметическое списка, не создавая список в памяти.

Если список не создается в памяти, то списка нет. И проблема хаскеля не в том, что список создается в памяти (если бы он и создавался, пусть там параллельно проходу по ф-и в силу ленивости, никто бы претензий не предъявлял) - в памяти создается ворох ссылающихся друг на друга санок. Которые занимают места многим больше, чем занимал бы список.

Многие проблемы с ленивостью хаскеля решаются расставлением bang patterns в объявлении типа. И контрол-флоу для этого в голове держать не обязательно.

Многие но не все. Более того - для того чтобы знать, что декларация у типа решит проблему, надо как раз понимиать как будем с этим типом работать (на уровне control-flow).

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

Что тебе может помешать пониманию хаскеля, если ты знаешь его синтаксис и семантику? =)

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

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

Нет, с длинными именами типа foldMonadWithNoReturn и foldLeftStrict было бы вполне удобно. С короткими удобнее.

Длинные и говорящие имена, конечно же, всегда лучше короткого невнятного говна. Почему в хаскеле неудобно с длинными именами, я выше как раз объяснил - синтаксис хаскеля их по факту «не поддерживает». Потому что это не продакшн язык. Вот джава - продакшн язык, длинные имена код не портят, он не становится от них менее понятен. Наоборот - синтаксис стимулирует использовать длинные имена. В хаскеле все не так - там ф-я длиннее строчки уже «слишком длинная», блоки никак не выделяются, даже основной инструмент оформления кода (скобки) намеренно не используется, с длинными именами блоки перестают влезать в «поле зрения», не вмещаются на строке, синтаксиса для оформления вложенных конструкций в хаскеле по сути и нету вовсе (шел 2017, напоминаю). В результате имеем то что имеем- либо ты пишешь однострочники в стиле перла, либо ты ничего не пишешь.

Нет там однобуквенного нейминга. Твои придирки нелепы.

Как это нет? Практически все типы-аргументы однобуквенны. 3/4, наверное, аргументов ф-й - однобуквенны. Однобуквенные нерегламентированные преффиксы/суффиксы - опять-таки норма. Однобуквенные локальные переменные - норма.

Нет при изучении хаскеля проблем с foldl/foldl'.

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

Я не обсуждал «изучаемость» хаскеля. Ну, конечно, он изучаем. Но вот для чего-то большего, чем рассмотреть какие-то (иногда интересные) CS-идеи на своем примере - уже не приспособлен.

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

А можно тогда увидеть идиоматический код решения той же задачи на хаскеле (эмуляция мутабельного состояния)?

Задача была среднее арифметическое списка посчитать.

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

То есть разница только лишь в том, что одно прибито гвоздями, а другое — нет? =)

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

То есть пока пишешь факториалы, помнишь разницу между foldl и foldl', а как только, прости госпади, «продакшн», то сразу нужно каждый раз в справочник лезть? :D

Давай без «грубо», давай как есть, четко и ясно.

Четко и ясно я написал изначально:

someFunctionM :: Monad m => a -> ... -> m b
someFunctionM_ :: Monad m => a -> ... -> m ()

Ты, вроде, говорил, что там какая-то логика. Если есть логика - значит, можно указать причину, почему выбран такой способ, а не какой-то иной. А тут «просто наугад взяли» - это логика?

Взяли лаконичное удобное обозначение. Одно из возможных.

Если список не создается в памяти, то списка нет. И проблема хаскеля не в том, что список создается в памяти (если бы он и создавался, пусть там параллельно проходу по ф-и в силу ленивости, никто бы претензий не предъявлял) - в памяти создается ворох ссылающихся друг на друга санок. Которые занимают места многим больше, чем занимал бы список.

Да, это печально. Что еще я могу сказать? =) Берешь профайлер в руки и исправляешь.

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

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

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

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

То есть разница только лишь в том, что одно прибито гвоздями, а другое — нет? =)

Разница в том, что одно поведение понятно и ожидаемо, а второе - непонятно и неожидаемо. Код с понятным и ожидаемым поведением - хороший код. Код с непонятным и неожидаемым поведением - плохой код.

То есть пока пишешь факториалы, помнишь разницу между foldl и foldl', а как только, прости госпади, «продакшн», то сразу нужно каждый раз в справочник лезть? :D

Так ведь foldl' это только пример. Если бы такое было исключением и встречалось редко - хрен с ним, ну бывает. И что? Пусть бывает. Но для хаскеля это норма, более того - язык стимулирует писать именно так (то есть предпочитать неправильные решения)

Четко и ясно я написал изначально:

Ты сказал, что _ - это логичное и понятное обозначение. Я вот у тебя два раза попросил ясно и четко объяснить, что оно, собственно, обозначает и какова логика его выбора. Ты вместо ответа несешь и даешь нерелевантные ссылки. Давай я напишу шаблон ответа за тебя: «_ в имени функции обозначает, что функция ..., он выбран, потому что ...». Что следует поставить вместо многоточий?

Взяли лаконичное удобное обозначение.

Иными словами, выбрали рандомный значок. Окей.

Да, это печально. Что еще я могу сказать?

Не стоило с самого начала кукарекать на эту тему.

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

Длинные и говорящие имена, конечно же, всегда лучше короткого невнятного говна. Почему в хаскеле неудобно с длинными именами, я выше как раз объяснил - синтаксис хаскеля их по факту «не поддерживает». Потому что это не продакшн язык.

херня

f = groupByUserSpecifiedFunction
        (applyBinaryOperatorToResultsOfFunction (==) length)
  . pickeElementsThatSatisfy ("a" `isPrefixOf`)  
  . applyFunctionToElementsOfList  
        (applyFunctionToElementsOfList toLower)

Если тебе так больше нравится, то пожалуйста

В хаскеле все не так - там ф-я длиннее строчки уже «слишком длинная», блоки никак не выделяются, даже основной инструмент оформления кода (скобки) намеренно не используется, с длинными именами блоки перестают влезать в «поле зрения», не вмещаются на строке, синтаксиса для оформления вложенных конструкций в хаскеле по сути и нету вовсе (шел 2017, напоминаю).

Каких вложенных конструкций? Есть let и where. Есть даже фигурные скобки и точка с запятой для ценителей ;)

Как это нет? Практически все типы-аргументы однобуквенны. 3/4, наверное, аргументов ф-й - однобуквенны.

Вот я открываю объявление вектора из c++:

template<
    class T,
    class Allocator = std::allocator<T>
[quote] class vector;[br][/quote]
T — одна буква. Почему тогда тебя удивляет аналогичная ситуация в хаскеле?

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

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

Но «увлекаться всякими линзами» = смысл написания кода на хаскеле. Это считается крутым и правильным. Если бы автору линз комьюнити насовало вонючих хуев в рот, и всем кто использует подобные библиотеки - тоже совало бы те же вонючие хуи, то хаскель сразу стал бы намного более хорошим языком. Возможно, потом бы и синтаксис поправили. Но комьюнити - говноеды.

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

Разница в том, что одно поведение понятно и ожидаемо, а второе - непонятно и неожидаемо. Код с понятным и ожидаемым поведением - хороший код. Код с непонятным и неожидаемым поведением - плохой код.

Почему оно непонятно, ты не объяснил. Почему неожидаемое поведение — тоже.

Так ведь foldl' это только пример. Если бы такое было исключением и встречалось редко - хрен с ним, ну бывает. И что? Пусть бывает. Но для хаскеля это норма, более того - язык стимулирует писать именно так (то есть предпочитать неправильные решения)

Да прямо таки стимулирует. Палкой по рукам бьет. Приведи еще примеры.

Ты сказал, что _ - это логичное и понятное обозначение. Я вот у тебя два раза попросил ясно и четко объяснить, что оно, собственно, обозначает и какова логика его выбора. Ты вместо ответа несешь и даешь нерелевантные ссылки. Давай я напишу шаблон ответа за тебя: «_ в имени функции обозначает, что функция ..., он выбран, потому что ...». Что следует поставить вместо многоточий?

Сто раз уже написал.

Иными словами, выбрали рандомный значок. Окей.

Да, как и с тильдой в c++, как и вообще со всеми обозначениями в этом мире.

Не стоило с самого начала кукарекать на эту тему.

Следи за словами, а то мамке тебя сдам ;)

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

херня

Что херня? Ты же сам и продемонстрировал, что вышло нечитабельное говно. Почему? Потому что синтаксис хаскеля не позволяет оформить подобный код по-человечески. В итоге надо писать однострочники. А чтобы получались однострочники - нужны короткие нейминги.

Каких вложенных конструкций? Есть let и where.

Не стеснйся, продемонстрируй как выглядит let внутри if-блока, который сам вложен в let внутри ifa (двукратное вложение, вполне нормальная ситуация, встречающаяся в императивных языках регулярно и не представляющая в них никакой проблемы).

Почему тогда тебя удивляет аналогичная ситуация в хаскеле?

Потому что есть большая разница между «просто какойто шаблонный аргумент» и «типовая переменная имеющая вполне конкретный смысл и использующаяся в конкретном контексте». Аналогично как с ф-ей - если твоя ф-я принимает какоето целое число, ну так можно и назвать ее аргумент как «n». Число и число, чего добавить? Но если по смыслу этому числу, например, является длиной какого-то массива, то нормальный человек ввместо n напишет arrayLength, или хотя бы length.

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

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

Почему оно непонятно

Оно непонятно, потому что невыводимо. Откуда я могу вывести, что значит _ на конце?

Почему неожидаемое поведение

А какие могут быть ожидания от _ на конце, если в специифкации языка и общепринятых гайдлайнах ничего по этому поводу нет? Откуда этим ожиданиям вообще взяться?

Да прямо таки стимулирует. Палкой по рукам бьет. Приведи еще примеры.

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

Сто раз уже написал.

Не написал ниразу. Еще раз, вот шаблон:

«_ в имени функции обозначает, что функция ..., он выбран, потому что ...».

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

Да, как и с тильдой в c++, как и вообще со всеми обозначениями в этом мире.

В с++ этот значок у деструктора ставят потому, что так указано в спецификации языка. Которая одна для всех. В хаскеле ' у строгих функций иногда ставят, а иногда не ставят, иногда ставят в каких-то других (неизвестных) случаях, а иногда не ставят, этот суффикс может что-то (что угодно) обозначать - а может и не обозначать (в зависимости от уровня аутизма конкретного автора кода). И определить, в чем его смысл в данном конкретном случае - никакого способа нет (не разбирая исходники, конечно же).

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

Что херня? Ты же сам и продемонстрировал, что вышло нечитабельное говно. Почему? Потому что синтаксис хаскеля не позволяет оформить подобный код по-человечески. В итоге надо писать однострочники. А чтобы получались однострочники - нужны короткие нейминги.

Напиши код на каком-либо другом языке с «правильными именами», сравним.

Не стеснйся, продемонстрируй как выглядит let внутри if-блока, который сам вложен в let внутри ifa (двукратное вложение, вполне нормальная ситуация, встречающаяся в императивных языках регулярно и не представляющая в них никакой проблемы).

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

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

Так зачем надо было кукарекать про типы-аргументы? ;)

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

Оно непонятно, потому что невыводимо. Откуда я могу вывести, что значит _ на конце?

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

А какие могут быть ожидания от _ на конце, если в специифкации языка и общепринятых гайдлайнах ничего по этому поводу нет? Откуда этим ожиданиям вообще взяться?

запускаешь ghci.

*Main> :t mapM_
mapM_ :: (Monad m, Foldable t) => (a -> m b) -> t a -> m ()
*Main> :t mapM
mapM :: (Monad m, Traversable t) => (a -> m b) -> t a -> m (t b)
Это все, что тебе надо знать.

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

Напиши код на какои-либо другом языке с «правильными именами», сравним.

f lst = lst.applyFunctionToElementsOfList(x => x.applyFunctionToElementOfList(toLower))
           .pickeElementsThatSatisfy(x => "a".isPrefixOf(x))
           .groupByUserSpecifiedFunction((x, y) => x. length == 

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

А при чем тут это? Разговор шел о том, что в хаскеле нету средств для оформления внутренних блоков кода. Я привел пример такой задачи - вот тебе лет внутри ифа внутри лета вынутри ифа. Покажи сперва, как это будет на хаскеле, я покажу, как те же блоки выглядят на императивном языке.

Так зачем надо было кукарекать про типы-аргументы? ;)

Затем, что однобуквенные типы-аргументы в хаскеле вместо нормальных имен - распространенный рак.

anonymous
()
Ответ на: комментарий от anonymous
f lst = lst.applyFunctionToElementsOfList(x => x.applyFunctionToElementOfList(toLower))
           .pickeElementsThatSatisfy(x => "a".isPrefixOf(x))
           .groupByUserSpecifiedFunction((x, y) => x.length == y.length)

побилось

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

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

Конечно, выводима. Из спецификации языка, которая известна любому программисту и для всех - одна.

Это все, что тебе надо знать.

Мне надо знать, что принято подразумевать под _ на конце. Я не вижу, как получить эту информацию из приведенных тобой типов. Продемонстрируй вывод, пожалуйста.

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

С тем же успехом можно придраться к c++, почему там деструкторы обозначаются тильдой

ЕМНИП, у использования тильды для обозначения деструктора был свой смысл: операция ~ в C и C++ обозначает «дополнение до единицы». А деструктор класса служит дополнением к конструктору класса. Отсюда и переиспользование уже имевшегося в языке символа операции «дополнение до единицы».

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

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

Позволяет. Проблема в том, что не заставляет.

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

Все элементарно разбивается на мини-функции.

в хаскеле же очень часто параметров у типов много и имеют они вполне конкртеные

Для этого придумали newtype.

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

Я привел пример такой задачи

Ты конкретный код давай, чтоб не кукарекать потом.

Затем, что однобуквенные типы-аргументы в хаскеле вместо нормальных имен - распространенный рак.

Да, это проблема, математики быдлокодеры те ещё.

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

И чем вот это

f lst = lst.applyFunctionToElementsOfList(x => x.applyFunctionToElementOfList(toLower))
           .pickeElementsThatSatisfy(x => "a".isPrefixOf(x))
           .groupByUserSpecifiedFunction((x, y) => x.length == y.length)
лучше вот этого:
f = groupByUserSpecifiedFunction (\x y -> length x == length y)
  . pickeElementsThatSatisfy ("a" `isPrefixOf`)  
  . applyFunctionToElementsOfList (applyFunctionToElementsOfList toLower)
?!?

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

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

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

Ты конкретный код давай, чтоб не кукарекать потом.

Я описал требования конкретнее некуда.

Да, это проблема, математики быдлокодеры те ещё.

Какие математики? Подавляющее большинство хаскелистов знает математику хуже средней третьекурсоты.

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

Позволяет. Проблема в том, что не заставляет.

Покажи.

Все элементарно разбивается на мини-функции.

Верно! Именно об этом я и говорю - в синтаксисе хаскеля можно писать только функции-однострочники. Но:

1. определять мини-функции - тоже не всегда хорошо, так как лишняя декомпозиция вредна.

2. это же лениво! лучше набыдлокодить перлостроку!

Для этого придумали newtype.

Так в newtype аргументы и называют a, b, c...

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

лучше вот этого:

Тем, что этот код скейлится.

let x = lst.applyFunctionToElementsOfList(x => x.applyFunctionToElementOfList(toLower))
           .pickeElementsThatSatisfy(x => "a".isPrefixOf(x))
           .groupByUserSpecifiedFunction((x, y) => x.length == y.length);
let y = blah-blah;
return f(x , y);

можно было бы написать:

do
    x <- lst >> applyFunctionToElementsOfList (applyFunctionToElementOfList toLower)
             >> pickeElementsThatSatisfy ("a" `isPrefixOf`) 
             >> groupByUserSpecifiedFunction (\x y -> length x == length y)
    y <- blah-blah
    return $ f x y
где >> - конвеер, вот только умник-хаскелист сразу заменит на applyFunctionToElementsOfList $ applyFunctionToElementOfList toLower после чего все сломается

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

Тем, что этот код скейлится.

Что за херню ты несешь?

let x = groupByUserSpecifiedFunction (\x y -> length x == length y)
      . pickeElementsThatSatisfy ("a" `isPrefixOf`)  
      . applyFunctionToElementsOfList (applyFunctionToElementsOfList toLower)
      $ lst
    y = blah-blah
 in f x y
Waterlaz ★★★★★
()
Ответ на: комментарий от anonymous

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

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

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

си был каваен и няшен

Ключевое слово здесь «был». Сейчас он мало кому нравится

синтаксису подражают java, js. с с++ и с#

Код выглядит совсем по разному. Я Java программист, когда читаю код на C — почти ничего не понимаю

а что, нельзя было сделать также?

Сделали же. Функциональному стилю теперь подражают java, js. с с++ и с#. И это здорово уменьшило необходимость писать императивную лапшу, как C в своё время уменьшил необходимость писать лапшу ассемблерную

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

Что касается «джавы-союзника» то речь шла про синтаксис. Джава очень похожа на С++. Похожа настолько что даже генерики в ней сделаны с такими же треугольными скобками, как в С++. То есть человек, писавший на С, может плавно перейти на С++, на ходу доучивая фичи по мере надобности, а может на жаву после врубания в ряд особенностей. И с С++ на жаву перейти тоже не проблема. Да, в жаве есть аннотации, и это сложная штука для С++ника. Но в целом crash-course проходится за две недели и дальше все понятно. Обратно по идее тоже легко перейти, но некоторые переносят туда подходы, которые в java прощались, а в С++ - нет, и потом вайнят. но это уже оффтоп. То же самое про С#: нет проблем для программиста на С++ или Java перейти на С# и обратно. Это похожие языки, хотя и разные и они занимают 90% доли софта на десктопе. А в вебе есть javascript который тоже вполне си-подобный.

Здесь очень много фантазий, по крайней мере про Java

ФП сильно отличается от этих 90%(императивных языков) идеологически

Тем что позволяет удобнее и безопаснее использовать указатели на функции?

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

Я когда читаю код на системных языках думаю так же

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

Какие проблемы?

1. Лишние движения
2. Можно посмотреть и не понять
3. Людям плохо знающим язык компилятор позволит писать плохие названия

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

у жабнутых проблема другая: им когда они зачем то пишут на c++ кто-то подло обсирает шаровары.

А это, кстати, из-за знакомого синтаксиса: ожидаешь, что одинаковый код будет работать одинаково, и в большинстве случаев ожидания сбываются...

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

С тем же успехом можно придраться к c++, почему там деструкторы обозначаются тильдой

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

I60R ★★
()
Ответ на: комментарий от Waterlaz
f = groupByUserSpecifiedFunction
        (applyBinaryOperatorToResultsOfFunction (==) length)
  . pickeElementsThatSatisfy ("a" `isPrefixOf`)  
  . applyFunctionToElementsOfList  
        (applyFunctionToElementsOfList toLower)

В продакшене пишут примерно так:

fun validate(userInput: String)
    = Observable
    .just(userInput)
    .filter{ it.endsWith('a') }
    .map{ it.toLowerCase() } 

Либо как здесь

I60R ★★
()
Последнее исправление: I60R (всего исправлений: 2)
Ответ на: комментарий от I60R

Ты забыл главную проблему - в большинстве случаев строгие ф-и обзывают без ' и с ' обзывают нестрогие функции.

По-этому на самом деле конечно мы знаем, что foldl' - строгая, но не потому что там ', и ' обозначает строгую, а потому что помним что строгое название у свертки вот такое. И если будет другая ф-я с ' то никто в здравом уме от нее строгости не ожидает по дефолту.

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

То есть, кода не будет? В точности как и «логичного объяснения», что такое _ на конце. Ожидаемо.

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

Здесь очень много фантазий, по крайней мере про Java

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

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

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

Бред полный.

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

То есть, кода не будет? В точности как и «логичного объяснения», что такое _ на конце. Ожидаемо.

То есть ты здесь код первым никогда писать не собираешься, да?

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

Ты же совсем не то написал. ду-нотация где?

И когда тот код успел стать монадическим? Или именно это в твоей вселенной называется «скейлится»?

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

Ну, хорошо, если хочешь с do, то будет с do

do
    x <- lst >>= applyFunctionToElementsOfList (applyFunctionToElementOfList toLower)
             >>= pickeElementsThatSatisfy ("a" `isPrefixOf`) 
             >>= groupByUserSpecifiedFunction (\x y -> length x == length y)
    y <- blah-blah
    return $ f x y

И прошу заметить, что этот код потенциально делает существенно больше, чем твой «императивный» код.

где >> - конвеер, вот только умник-хаскелист сразу заменит на applyFunctionToElementsOfList $ applyFunctionToElementOfList toLower после чего все сломается

Угу, домовой прибежит и заменит.

Так что тут не «скейлится»?

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

Мне кажется, Александреску folly в facebook-е пилил, пока её не опенсорснули.

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

И прошу заметить, что этот код потенциально делает существенно больше

Он вообще ничего не делает, потому что не тайпчекается. Откуда ты бинд высрал?

Так что тут не «скейлится»?

Я вроде внятно объяснил, нет? Тот код, что ты привел, на хаскеле не пишется, потому что хаскелисты не пишут скобки, они пишут $

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

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

Если используешь do-нотацию, то не используй bind, >> внутри. Rule of thumb меджу прочим. Guideline есть, единственно верного варианта нету, но все же общая часть совпадает, отличаются совсем уж мелочи.

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