Episode Transcript
Друзья, привет. Это подкаст Организованное программирование. Я Кирилл Макенин, его ведущий. И сегодня у меня в гостях Саша Вершилов, а, который, на самом деле, у меня уже один раз был. Мы с ним разговаривали про ОРМИ. А что, кстати, многих людей немножко удивило, потому что Саша известен немножко другим. Саша в первую очередь известен тем, что он пишет на Гаскеле вот уже, наверное, 15 лет, если что ты меня, Саша, поправишь, да? И каждый раз, когда я спрашивал о том, а кого позвать из сказки или комьюнити, с кем можно это всё обсудить и поговорить, все пальцем показывали на Сашу как на одного из самых влиятельных, можно я так назвал, людей на небосклоне функционального программирования на русском языке. Я бы не сказал, что самых влиятельных, но спорить не буду, раз уж говорят. Я начну с шутки. А значит, когда-то я Вандеве работал, там Махоткин такой был человек. Если ты помнишь, он редактором был в том числе, перевозил пирса типы функциона типы в языках программирования. И а у нас тогда работал Хаскель программист. И значит, мы такие сидели на полном серьёзе, обсуждали: "Так, нам нужен второй Хаскель-программист". И Махоткин такой говорит: "А, ага, и тогда у нас будет самая большая команда Хаскельпрограммиста в России".
Ну, в то время это действительно было так. Было так, хотя мне казалось, что в то время было это популярней. В те времена Хаскель действительно был популярным, но он был больше популярным так на кухнях тихонечко писали у себя и меньше выходил в продакшн, потому что в тот момент язык очень интересный. А как раз в те времена был, наверное, пик популярности функциональных языков и Хаскеля, в частности. Вот про что можно поговорить, потому что было очень интересное время. Им интересовались как люди сами по себе, так и в больших компаниях появлялись какие-то небольшие проектики, заканчивающиеся с разной степени успешности.
Ну что, давай, знаешь, наверное, с чего начнём. У нас сегодня большой выпуск про Хаскиль, а, как все уже, знали, и мы постараемся, ну, поскольку, в принципе, про Хаскель-то видосов достаточно, вот чем-то таким магическим обладает язык, да, что про многие забывают, они уходят, а вот Хаскель он всегда остаётся, несмотря ни на что. Давай, наверное, мы сейчас исторический контекст, и прикладную разработку, и теоретические какие-то вещи разберём. Давай начнём вообще с того, что почему Хаскель вот в мире м вообще языков программирования стоит немножко особняком, даже не среди функциональных языков, а в принципе обладая каким-то таким вот притягательно магическим какой-то там где-то там Хаскель. Таких такого больше нет. Вот Акамал про него так не говорят, Эликсир Ирланг про него так не говорят, Кложа как будто бы сейчас про неё так уже не говорят, хотя тоже был такой. А вот Хаскель он всё время как бы остаётся. Мне кажется, что здесь прямо сложился набор - причин, как реальных, так и мифических, которые создали некоторый ареол вокруг языка. Ну, во-первых, как язык появился? Давным-давно, когда было много академиков и много разных языков и изуча и и функциональные языки, ну, и в целом теория программирования активно изучалась, возникла логичная мысль: почему каждый третий человек начинает писать свой язык для того, чтобы концепции некоторые проверить, а не сделаем ли мы какой-нибудь один академический язык, на котором будем исследовать? Соответственно, примерно так появился язык. В нём было выбрано очень то, что его отчасти отделяет от всех других языков программирования, что он ленивый. Ленивый по умолчанию. И это очень важно, потому что, да, ленивость она есть сейчас и в других языках с помощью разных способов, но если это не встроено в сам язык и не находится в его базе, то всем будет лень делать это эффективно и хорошо. В итоге во многих языках, да, действительно есть, но оно работает не очень и писать не хочется. В этом в то время как в Хаскеле, поскольку, ну, от этого никуда не уйдёшь, поддерживать придётся, оно работает. И это его очень сильно отделяет от других языков, да, в этом есть плюсы и минусы. Это приводит куча разных проблем, о которые мы наверняка так или иначе сегодня затронем. А, но главное в том, что это даёт и много полезного. Соответственно, если, наверное, нужно сказать про ленивость, строгость и что-нибудь прочее, что это такое, раз уж заговорили, когда у нас есть функция, и мы передаём в неё аргумент, и дальше она должна что-то вычислять. У нас есть выбор, что мы делаем. Мы вычисляем всё до того, как передаём его функцию, или мы функция его вычисляет где-то там уже внутри. А, соответственно, это приводит к разным моделям поведения, разным свойствам. И есть мнение, что второй вариант ближе к математическому, проще делать разные преобразования, ну и, соответственно, делать программу более эффективной и работать с ней как с математическими объектами. А это как бы строгость. Соответственно, ленивость делает ещё шаг вперёд. Что помимо того, что мы вычисляем только, когда нам потребуются данные, мы ещё и запоминаем результат вычисления. То есть у нас вычисление не дублируется, мы не посчитаем пару раз, что добавляет эффективность. ну и немножко хороших свойств. Вот, соответственно, взяли такой язык, начали делать, начали использовать. Соответственно, поскольку появляется общи�� язык, с которым, а, который можно использовать для исследований, то вокруг него собирается некоторая академическая среда, где появляется человек, появляется идея, пишется, он добавляет это в компилятор, пишет статью, а, это проверяют, возможно, работает, э, ну, и это всё копится в самом языке. И в итоге появляется язык, вокруг которого много статей, много работы. Он появляется на всяких конференциях. Периодически появляются новые статьи. Причём работа идёт, как и со стороны чистой академии, а как мы красиво изобразим какой-то интересный эффект возмо какую-то интересную концепцию, которая может нам писать. Так и было много работы, а как мы это сделаем эффективно, которая шла одновременно. В итоге, где-то к девяностым годам, началу среди, значит, к концу девяностых, началу дсячных, а позже, мы получили язык, который вполне себе академический, по которому много литературы, которая выглядит интересной, которой можно доверять, которую проверяют другие люди, а не просто кто-то написал красивый редактор посмотрел и сказал: "О'кей". И который можно использовать. Можно взять вот скачать все эти статьи, почитать, понять, веришь ты, не веришь, как это делали, как считали, что мерили. Вот. И язык при этом собирал вокруг себя вот этот ареол академичности. Он был хоть как-то практичным, и он был близок к математике. А математику многие любят, как бы если это в математических концепциях выражается, значит, наверное, с помощью языка можно всё изобразить, написать правильный код, написать всё красиво. Вот. И это многих притягивало. Человек, который попадает, не знаю, там, э, оказывается в условном Гугле в то время. При этом он вышел, получил себе CS какой-нибудь компьютер science а образование. Он слышал об этом языке, у него ещё математическое образование, ему интересно это попробовать, он это пробует. Вот примерно в таком состоянии мы оказались в тот момент. И это, наверное, пик языка. очень много ожиданий по то, что всё заработает, всё будет классно, правильные концепции, и мы получим отличный новый мир и забудем все старые языки как что-то страшное из прошлого века. Вот. И плюс-минус на этом наследии язык живётся и сейчас, потому что все знают, что он был связан с академией, что при этом на нём что-то можно писать. При этом он будто бы очень математичный и всякие вопросы: "А нужно ли знать теорию категории для того, чтобы писать на хаске или прочая ерунда? Вот, мне кажется, примерно так. А, а в каком году он появился? Не восемьдесят девятый или восемьдесят девятый? Да. Восемьдесят девятый, да. 1 апреля было это сделано, как такая главная шутка. Угу. Угу. Но при этом он же наследник был Эмля. То есть это не то, что с нуля сели и придумали. Там же целая цепочка была языков, да? Можешь вот про двух? Да, естественно, язык придумывали не с нуля. Э, я здесь буду очень осторожным поводу Эмеля, Миранда и всего остального. Здесь лучше поговорить с кем-нибудь, кто знает хорошо историю языков программирования, потому что очень легко собрать. А, но главное, что он действительно был построен на основе уже предыдущих языков. Это не была какая-то разработка с нуля. К этому моменту было уже лет 20 с лишним исследований в этой области, идей. Э, вот. Ну и, соответственно, был собран комитет и, да, язык ведомый комитетом, который собирается, решает, какой будет стандарт, как это будет работать. И так это работало вот как раз в то время. Кто это финансирует? То есть где вот это ядро находится? С исторической точки зрения, я не скажу, кто в тот момент кто был. В разное время участвовали разные компании. А на протяжении очень большого срока работы очень сильно влиял Microsoft Research, но ни в какой момент язык не был, а, не принадлежал какой-то одной организации, компании или структуре, которая это оплачивала. А, соответственно, большая часть разработки языка велась в, ну, в академической среде. Кто-нибудь пишет своё PhD, получает за это какие-то деньги, соответственно, пилит, делает часть языка. PhD заканчивается, ему надоедает, он уходит дальше этот университет не финансирует. Вот примерно так. Ну, то есть foundation был создан сразу, насколько я понимаю, foundation, именно foundation языка был создан уже весьма недавнее время, и это было организовано, потому что до этого какой-то единой точки, которая распределяла финансы, что-то делала, её не было. Сейчас Foundation тоже, хотя он и есть, собирает в основном донаты. А, и в основном это делается на на Данеation и распределяет уже дальше как-то ресурсы, но это больше на инфраструктурные проекты и что-нибудь такое, а не на проект, а не на само развитие языка, потому что развитие языка больше делается различными компаниями, которые так или иначе используют хаски либо в продакшене как используемый язык, либо те университеты, где продакшн - это новые статьи. Будем честны, для них это тоже продакшн и язык там используется. Просто хочется сказать, что с одной стороны получается, ну, действительно, у меня тоже есть такое ощущение, что вот именно близость к этой математике и возможность её пощупать именно там, а не в каком-то любом другом языке практически, да, это то, что делает его привлекательным постоянно для одной постоянной аудитории. Поэтому и популярность примерно всегда остаётся как бы постоянной и не выходит за рамки там какого-то границы. Но что хочется ещё добавить, что как будто и ниже оно не опустится, потому что, а, грубо говоря, этот язык, мм, а, смотри, вот многие языки приходят и уходят, они теряют актуальность, они становятся неактуаль, ну, по разным причинам. Хаскель умудрился занять такую нишу, что он с одной стороны и весь академический его используют все во всех ипостасях, мы сейчас поговорим о том, какое влияние оказал на реальную индустрию, а при этом он и есть в продакшене, и способен этот продакшн поддерживать, и поэтому получается, что у него есть такая же подпитка. А, и скорее всего мы, наверное, не говорим о том, что когда-то на Хаскиле будут запускать, это будет стандартный язык для программирования, но мы понимаем, что он всегда где-то присутствует вот как Linux, да, он там всю свою жизнь там 2% десктопа занимает на серверах везде. Здесь тоже в академической среде везде. То есть он является частью, наверное, обязательного изучения. Если у тебя в компьютер Science есть ну серьёзный компьютер Scienceс, там невозможно не изучать Хаскиль, правильно ведь в университете, да? как насколько он в университетской среде, конечно, вопрос такой. То есть многие университеты любят какие-нибудь языки программирования, особенно если он был написан в его рамках. И основной основным языком в университете, естественно, является тот. Но но при этом так или иначе Хаски всё равно изучают, потому что он есть уникальные ниши, которые он занимает. А с одной стороны, это система типов плюс её развития, потому что там разные исследовательские направления. Во-вторых - это ленивый язык. В-третьих - это чистый язык, функциональный. Если хочется, э, и для того, чтобы иметь хорошо обученного студента, который знает компьютер scienceс, а язык очень хорошо закрывает много ниш, с которыми, ну, просто необходимо познакомиться для того, чтобы иметь хотя бы полное образование, представление о том, что вообще бывает, и не начинать переизобретать то, что уже переизобретено, и знакомиться с некоторым общим знанием, которое человечество уже к этому времени получило. Настоящий чистый кот. Да, чистый код. Но не только в книжке. Кстати, я я прямо небольшой комментарий. Я буквально на днях переписывался под каким-то постом у себя на на тему кода или или, короче, с кем-то переписывался. И когда я употребил несколько раз слово чистый и представляешь, я в этот момент понял, что а человек, когда я говорю это слово, он клин слово подразумевает, а не, то есть нечистоту. И я и я как бы такой думаю: "Блин, а что-то я то ли забыл, то ли я давно с таким не сталкивался, то ли вообще первый в жизни с таким столкнулся, что у человека вот нету этой картинки". И, ну, я немножко объяснил и рассказал про эту разницу, но для меня это было какое-то, знаешь, такое открытие. Хмм, а когда говоришь слово чистота, надо говорить, какое английское слово мы имеем в виду. Это очень разные слова, да. Ну, мы поговорим об этом. Частота вообще очень важная часть, да, мы с тобой о ней чуть попозже поговорим подробно. По поводу того, что не будет ли теряться, не будет и что будет с нишей и использование языка. Если честно, последние годы, а появились языки, которые так или иначе начинают теснить хаскель и перетягивать к себе аудиторию. Естественно, нельзя не упомянуть о расте, потому что тоже в нём есть интересные концепции. У него есть, а важный подхо важные подходы к безопасности программирования, а к тому, чтобы дать больше гарантий, к тому, что то, что будет работать, будет работать. И чуть-чуть проще, а может даже и не чуть-чуть, а просто проще с перфомансом. Что тоже бывает важно, это если мы будем говорить, почему Хаскерем стали пользоваться меньше и почему он прошёл пик популярности, нам придётся про это поговорить. Да, ну это про прикладную разработку тут очень важно. Раз, потому что для академической это не то. С другой стороны, с академической стали появляться более популярными стали языки с пф, э, теорем прувера, то есть всякие лины, агды туда можно записать. А, соответственно, и таких языков стало больше, они стали более серьёзными и ими стали больше пользоваться. А раньше часто использовали хаскель, который, в принципе, не дотягивает до теорем пруеверов очень сильно, но уже что-то можно делать. И как бы сообщество, ну, и люди отчасти выросли до того, что они готовы уже идти дальше. Э и начинает проскакивать язык. Конечно, в Хаскеле идёт движение сильно в эту сторону, но оно идёт достаточно давно и будет идти ещё долго. Это, кстати, интересно, да, получается, он как бы такую нишу посередине занял, и у тебя появляются сильные специализированные языки. раз с точки зрения прикладной и остальные, которые ты назвал, Агада, кстати, и вообще много лет я про неё слышу, тоже там чёрт знает сколько времени, э-э, зависимыми типами и всем остальным, да, с другой стороны. И получается, что Хаскель как бы может в перспективе, ну, сильно даль далёкой, потому что это ещё не как в конце концов проиграть теоретически, да, из-за того, что у тебя специализированные штуки разгребут это всё. В принципе, вполне может, ну или может так оказаться, что человечество и понимание окажется на какой-то стороне или что нам надо уйти в одну область или что в другую. Здесь можно что угодно придумывать и что окажется, что какие-то какая-то из этих областей станет не так важна, и, соответственно, языки в другой области выиграют. При этом, э, ну, если честно, то, на мой взгляд, основной плюс Хаскеля как раз, что он находится вот в этой вот промежуточной нише, где, а, при наличии некоторого понимания, как работает язык и опыта, а, можно подобрать нужный тебе уровень, а, нужные тебе свойства, которые ты хочешь получить от решения, от языка, от своей системы. И это самое полезное свойство, которое лично для меня в нём существует. Кстати, я хотел одну вещь такую немножко отвлечённую сказать, а перед тем, как тему закончить. Скала же ещё по такому же принципу создавалась, да? И F#P, но они, правда, немножко от другого, но ладно, но скала в первую очередь тоже исследовательская. А она в итоге с Кацкелем так конкурировать не начала или конкретно в том университете, где это было создано, они там пытаются это пропагандировать? То есть какой статус? Мне просто даже интересно. Она же тоже исчезла вообще. На неё пророчили как замену Джавы. Она в прикладном программировании, особенно там, где используется Java экосистема, а она не пускает Хаскель туда вообще никак. То есть, ну, есть достаточно много проектов, направлений компании, которые так или иначе используют Скалу, потому что у них весь всё на Джаве, на это завязана куча инфраструктуры, а она важна как платформа. И Скала является вот таким решением, что мы можем получить много интересных технологий. Пока они не в Джаву, они прорастут, но будут прорастать ещё достаточно долго. А мы уже можем использовать сегодня. А в ЕПФле, насколько я понимаю, она была сделана и здесь и рядом с ним лучше словом Хаскель лишний раз на заикаться. Там она, естественно, выигрывает активно исследование и разработка идут. Как-то так. В целом по индустрии мне сказать сложнее. И там, и там вакансий не так много. И там, и там компания, разработка есть, и там, и там некоторые проекты закрывают, некоторые появляются. То есть в целом по больнице какая-то флуктуация, но на уровне существования. Дадада. Если кто-то скалист, напишите, интересно, потому что я помню историю, когда вот тоже этот был пик, когда, помнишь, там Тиньков особенно звучал вот в России очень многого было, а потом, конечно, оно, ну, слишком сложно и не особо никакого не приносило лью большого. Всё это на самом деле исчезло. сложно. Я сделаю вид, что я ничего не знаю, не смогу прокомментировать это утверждение. Ну, я имею в виду не в том плане, что оно совсем, то есть у тебя скорее LEC осталось, но так, чтобы массово там, знаешь, там с удовольствием. Мы стартуем новый проект Наскали, это больше никого не возбуждает. С Хаскилем, кстати, не так. С Хаскиль до сих пор может людей, так сказать, подбодрить каких-то определённых. Вот меня вот это всегда в нём поражало, что года идут, а вот Хаскель, если скажут, что новый проект на Хаскеле, это 100% заинтересует людей, и никто не скажет, что это какая-то чушь. Ну, кроме тех, кто слишком далёк от вот этого мира совсем. Это правда. Искать людей, слово хаски вакансии очень сильно помогает. А, во всяком случае это является точно плюсом, особенно если есть какой-то проект, команда, понимание, да, и для тех, кто ищет, это тоже плюс, потому что обычно кто все, кто откликаются на эти вакансии, с ними уже есть о чём поговорить всегда. Это прав. У меня есть один негативный опыт, а поскольку я работал в Ульяновске, а там сейчас небольшую историю про Льва Валкина. Те, кто знают функциональное программирование, конечно же, это имя слышали. А, легендарный вообще человек, создатель журнала Практика функциональное программирование, у него была компания Эхо, которой и самая большая команда ирлан разработчиков была, собственно, чуть ли не в мире, но одна из самых больших, она была, собственно, в Ульяновске. И поэтому, кстати, мы все болели очень сильно ирлангом. Те, кто в те года там жили, потому что вот самые крутые ребята на нём писали. И, естественно, Хаскель там тоже был. И Кложа была, собственно, там всё было в этом плане. Так вот, а я в это время в Андеве работал и был руководителем подразделения. И ко мне пришёл парень как раз от них, а, и он хаскилист. А, а мы писали на Руби. И, соответственно, у него задача была простая достаточно, что-то сделать на Руби. И вот он вместо того, чтобы воспользоваться Рубий и решить эту задачу, он 3 дня на Хаскиле Роутинг писал альтернативные рельсом. Ну и в конечном итоге мы расстались, но, ну, там просто человек как бы не пытался решать бизнес-задачу, он пытался писать на Хаскеле. Поэтому всё-таки мы про комьюнити с тобой немножко поговорим. Там вот есть немножко история того, что людям всё-таки, тем, кто там, меньше интересен бизнес и какие-то прикладные штуки, чем, собственно, сам факт хаскиля программирования и того. Ну не уголовное, просто есть такая тенденция. Смотри, я сейчас хочу такой блок зацепить перед тем, как двигаться дальше, чтобы мы вот сейчас много про историю говорили, про его особенно некое состояние, про его влияние, потому что вот это я 100% уверен, не все знают. У нас был уже сейчас небольшая подсказка, что Microsoft resarch в него сильно вкладывался. И когда люди узнают, какие вещи из Хаскеля пришли в их собственные языки, которыми они радуются и гордятся, знаешь, как бывает, когда они там есть люди 100%, которые его хейтят или вообще говорят функциональщино там [ __ ] и никому не надо. И сейчас, когда они узнают, как, например, на Джаву повлиял Хаскиль, я думаю, у многих откроют сорты, когда мы поговорим про дженерики. Ты знаешь, да ведь я просто вдруг подумал, может быть, ты не знаешь, что про дженерики в Джаве, про то, когда они появились. Ну да, нет, то, что Genрики в Джаве создатель собственно один из скор девелопер разработчиков Хаскеля это сделал. Это, кстати, я не знал, ну или знал, но не помнил. Вот здесь тоже мне чуть-чуть сложно будет, потому что я, как фанат Хаскеля и его любитель, могу приписывать ему, а функции, что это придумали там, хотя на самом деле они были придуманы где-то ещё, и он их адаптировал. Это я оттуда узнал. Э, вот дженерики в Хаскеле, о, в Джаве появились благодаря Хаскелю. Просто так вот сразу начнём с козырей. И это было довольно давно. Да. Да. Здесь с дженериками это нужно говорить про, а, наследование, как это происходит, про разные типы и, соответственно, что, а, вот это вот как разрики в Хаскеле - это основное то, что в нём было и основной тип для абстракции кода, основной подход к абстрагированию кода, который был в языке, в общем-то, чуть ли не единственным на протяжении долгого времени. Ну, можно обобщить, да, что фактически речь идёт про метрический полиморфизм и, собственно, его во все языки классические, собственно, тащили из функциональщины, потому что функциональщина, она вот этим богата, да, и это было с самого начала. И это очень важный, простой, но при этом а хорошо работающий механизм. Давай зацепим, наверное с такой стороны. А если мы откатимся, допустим, на 2000ные года, была такая история, что практически ни в каких, э, языках, ну ладно, там, кстати, я JavaScript не помню, в каком году появился, но он там точно был, да, ещё такой зача, он тогда языком не был по сути, да, но мы берём вот всё, что мейнстримовые были всякие там от C PHP, пёрлов и так далее. А чего везде не было? Ну, во-первых, практически нигде же не было а цепочек именно по обработке коллекций. А у тебя просто циклы были, с которыми ты работал. Что у нас там ещё туда входило? У нас не было лямбд нигде. Цепочки, лямбды. Ну и вообще использование функций как объекта первого класса. И это было далеко не везде, а где использовалось, а часто использовались всякие хаки типа трамплинов си там для того, чтобы сделать что-то похожее. А, соответственно, лямды сильно популяризировались во всём виде. и сказать callback styleминг примерно вот как раз вот с обработкой цепочков и цепочек и соответственно вот это вот объединяя прямо вот в этот вот стиль, как мы работаем. Ну и как не только с коллекциями, а и в принципе с какими-нибудь вызовами. Вот я делаю вызов, а потом мне, пожалуйста, проделай с результатом то это, а в случае ошибки уйди в другую ветку. Соответственно, вот эта вот штука, которая стала появляться активно в джесе, в тайпскриптах и там и всём прочем, а это, ну, я бы не сказал, что это хаскель, но это стандартный механизм, который использовался. А все это вдохновлено очень сильно функциональным. Да. Да. То есть очень была большая тенденция перехода функциональных фич в обычные языки. Прямо все очень хотели. Это прямо были вот много лет того, что так, давайте затащим, давайте затащим, а то очень неудобно. Мапы, фильтры, редюсы. Кстати, на сложный вопрос, но скорее появление все, да, про мапы фильтрадью здесь надо сказать, конечно, это не хас не с Хаскелем единым. Это было очень много где и в языках, которые были ещё до появления. Но с другой стороны здесь хаскель - это язык, в котором нету другого удобного способа. И а там он является очень удобным. То есть всякие ээ и вещи, когда, не знаю, когда начинал учиться программированию где-то там в девяностых и в школе ещё, и там говорили: "Вот рекурсия, но у вас есть стек, никогда не не смотрите страшная штука". И люди просто хватались за голову и убегали куда-нибудь, когда это слышали. И никак нельзя табу. А то в функциональных языках это основное средство для выражения. И на самом деле оно очень простое, очень удобное. И когда видишь, как это может работать, и когда, не знаю, при решении задачи она перекладывается на функции, на написание, просто вот читаешь текст, как как это должно работать, алгоритм, обычными словами, и просто переносишь это в код, и оно просто тупо работает. И всякие divй and conquer задача, вот всё это оно в языке очень хорошо ложится. Э, и это очень просто. И потом, возвращаясь в любой другой язык, ты смотришь на задачи уже по-другому. Не всегда нужно прямо один в один копировать, потому что понятно, опять же, в Хаскеле есть ленивость, которая из коробки хорошо работает, что-то похожее начинаешь делать в строгом языке, и всё разваливается на каждом шагу. Э, есть такие штуки, но в целом при некоторой тренировке, при некотором понимании, как во что оно должно переходить, всё работает. Так, слушай, я вспомнил, у меня прямо у меня список прямо появился, да. А почему хотел сказать? Потому что действительно, а, вот почти всё, с чем мы сталкиваемся в современном мире, то есть какая была проблема, я бы хотел так сказать. А, грубо говоря, если ты просто вдохновился функциональным языком, пошёл писать в JavaScript, с с редаксом была такая история, типа давайте писать всё иммутабельно, а потом куча, значит, статей на тему того, насколько это неэффективно, потому что у тебя там копирование постоянно и так далее. И, конечно, люди, которые понимают, и вот хочется, чтобы те, кто нас смотрели, понимали. Дело в том, что в функциональных языках почти все эти вещи, они не являются проблемой, потому что языки спроектированы так, что там всё это эффективно. А и в Хаскиле вообще эталон, то есть его, почему мы про него говорим, хотя не всё от него появилось, просто он в этом плане эталон, да, то в обычных языках м нужна была адаптация, и она произошла по многим вещам. И я вот ты сейчас начал говорить, я сразу вспомнил, смотри, деструктуризация и это всё пришлось из функциональных языков. паттерн матчинг сейчас, который, кстати, вот вообще последние годы все свечи, мэтчи появляющиеся там в Пайтоне, в Джаве, это всё оттуда пришло. А не факт, что самого, опять же, Хаскеля, но в собирательном виде. А ты обязательно вот сказал важную вещь по поводу иммутабельности и возможности параллельных вычислений и безопасности. У тебя м смотри иммул коллекции во всех языках. э у тебя все современные библиотеки с датамиотеки с временем вот всёвсв оно в новых версиях становится иммутабельным и я думаю что вот если так мы сейчас вспомним с тобой мы перечислим просто половину фич которые считаются классными во всех этих современных языках лёгкие потоки например в Хаскеле оно появилось достаточно давно а и оно очень хорошее о в те же времена не могу сказать что раньше было ирлан и как оно появилось. В моей истории сначала появился появился Хаскер, потом Ирланг, поэтому я не знаю. А, но в целом то, когда, не знаю, появились горутины и все радостно и счастливо прыгали и говорили: "Вот какая классная фича в языке, когда 10 лет до этого писал на другом, где всё было то же самое". Смотришь на это и немножко удивляешься, потому что вот вот рядом руку протяни и всё есть. А, да, есть отличия. Есть отличия, причём которые важные, как происходит там передача управления, э, и что в некоторых случаях может и в некоторых случаях принятые умолчания могут сильно влиять на то, что удобнее, но главное, что это было. И главное написать программу, в которой будет 10.000 потоков. Они будут ээ конкурентных, которые будут работать с IIO, радостно блокироваться, передавать управление, ничего не будет зависать. Звёздочка может зависать, но это совсем нужно постараться. Вот главное, оно не будет зависать, если писать нормально. Нормальный обычный код. И об и об этом вообще не надо думать. Всё просто работает из коробки. Это многого стоит. А понятно, что всё равно совсем низкоуровневый код был не очень удобный. Это, в общем-то, проблемная история. И проблемная история для хаскелиста, которого наняли и который писал роутинг 3 дня. Потому что если бы это произошло, не знаю, там через году в тринадцатом, четырнадцатом, пятнадцатом, то он бы просто уже взял готовый фреймворк, а, и не думал бы, и всё бы было. Проблема в том, что в старые года как раз, когда всё вот это вот было, были было куча куча вещей интересных подходов, направлений, кусочков, но не было собрано целого в тот момент. Ещё про одну вещь не могу не сказать, которая вот многие языки цепанула, и это, наверное, был ориентировочный год пятнадцатый, когда пошло. А, ну, кстати, мы ещё забыли сказать про optшнал, да, то есть аляйби, Монады и всё такое, это очень сильно распространились и пошли во все языки и очень активно сейчас много где используются, да. А, и я, знаешь, что помню? Я помню, что люди, которые вот именно в те года, когда практика функционального программирования выходила и мы все помешались, и кложа тогда вышла и вот это всё, я помню, что тогда была такая история, когда в каждый язык затаскивали, а делали специальные либы, которые очень популярны, быстро становились, когда у тебя всё строилось на комбинаторах, когда ты можешь пайплайны создавать, когда у тебя частичное применение функций, но всё это немножко было чужеродным, если ты помнишь. Я помню, вот в Пайтоне там чувак очень крутую библиотечку сделал, популярную, и там такая ситуация получилась, что всё это внедрялось в массовом э прямо массово, но поскольку оно было не родное, то, конечно, скорее оно вызвало в итоге отторжение. И в конце концов это ушло, потому что мы как-то вот про исключение даже говорили, когда у тебя с одной стороны есть исключение, а с другой стороны чуваки такие: "Давай монаду айвер тут затянем, сейчас будем тут leftрай разруливать и всё такое". у тебя просто скрещиваться код код перестал, да, из-за подходов, которые делали. Поэтому в том числе вот как бы оно для людей, которые не очень в теме и не до конца понимают, что с той стороны, оно выглядело, наверное, не очень. То есть вот потому что, ты знаешь, есть такая странная в каком-то смысле история, когда люди не просто, ну, язык и язык, какая тебе разница, вот прямо есть отторжение, что нет, функционально это вот прям прямо вот не то, так писать нельзя, это супер неэффективно и вообще как бы это противоречит тому, как мы вообще тут значит программы делаем. Ты встречаешься с этим мнением? Да, точно. Сталкивался. По разным причинам, мне кажется, у людей это возника возникает, но я не знаю, язык, учитывая, что язык занял какую-то такую нишу, в нём появились его, а, очень активные популяризаторы в разное время, это вывело его в какой-то, я не знаю, религиозный уровень, а когда к нему относится больше не как языко, а к какой-то идее концепции. А идея идея концепции, они встречают очень полярное мнение. А то есть кто-то просто ненавидит, потому что ненавидит, кто-то любит, потому что ничего другого быть не может. И это, наверное, играет в минус языку, потому что когда когда язык не не оказывается в такой ситуации, то к нему какое-то более спокойное отношение больше пробуют. В случае успеха, ну да, не такой максимальный успех. Все это не начинают как-то возносить, но в случае провала как бы о'кей, понял, принял, там здесь это хорошо, это нехорошо, там-то можно применять. Из-за вот этой поляризации возникает такое, что если язык не понравился, то всё, табу, никогда его не трогать, всё, что похоже, запретить. Как есть, видимо, человеки так работают. Кстати, значит, сейчас подумал, а, смотри, ещё, наверное, что нельзя не сказать. Мне прямо хочется вот прямо перечислить все эти штуки, потому что, говорю, влияние гигантское, генераторы, продолжение. Я почему-то думаю, что всё это тоже из функционального мира пришло, потому что, в принципе, концепция бесконечных списков, например, банально это очень на ленивость хорошо ложится. Да, это хорошо ложится на ленивость, учитывая, что вот эти вот как раз списки listreхs, которые, я не знаю, если на них после Хаскеля заглянуть в в Python, то на них просто без боли не посмотришь. И после рланга тоже самое. Ты такой приходишь после функциональщины, да, круто, но вы так это сделали, что если у вас хоть немножко вложенность, ты такой: "Что это за кошмар?" Причём даже без расширений, потому что с расширениями там возможности группировки, там чуть ли не SQL получаешь на этих лист компрехеншенах со всеми его возможностями по группировке, обработке там и прочему. Но даже в самом банальном варианте без расширения оно уже работает очень удобно, хорошо выглядит, а главное ещё эффективно работает благодаря разным оптимизациям. Тут тоже, кстати, часть оптимизации. Такое ощущение, что в обычные языки приехали дальше. Совсем банальная история, но иммутабельность помимо коллекции появления конст в разных языках, а такое ощущение, что тоже наследие языков, а иммутабельных. И, соответственно, что же во многом от функциональщины? Не уверен, но это проросло во многие языки. И главное проросло понимание о том, почему это может быть полезно и почему создание конст выражения - это лучше, чем говорить, что здесь переменна и незаметно её менять в следующей строке. Так что все теряют контекст. Кстати, далеко не везде в цепочках это проверяется, но, например, в Джаве это сделали. То есть там писать аэ код с побочными эффектами внутри мапа фильтра редюса нельзя. Ну то есть там какое-то ограничение при этом есть. Слушай, и ну и, наверное, последнее, чтобы закрыть, а то сейчас скажут: "Что-то вы задолбали уже этим." А есть последняя вещь и возможно самое главное, я не знаю, почему мы про неё забыли, это вывод типов: "А, ну, как бы здесь несколько вещей нужно сказать. Во-первых, с одной стороны, нужно, ну, как же, у нас тут есть C, например, у нас Паскаль был, э, есть, а, в котором есть типы, мы их пишем, как бы, что тут нового изобрели, а, то, что, не знаю, в ПХП стало можно аннотировать типы, разве это плюс какой-то? Э, вот здесь нужно понимать, что системы типов и а то, что можно выразить с помощью типов, имеет, в общем-то, очень большие градации и количество вот этих вот уровней. Если сначала типы были в языках, в основном для эффективности, мы говорим ячейку какого размера в памяти нужно выделить. Ну и максимум говорим о том, если у нас знаковая или безназнаковая чиселка, то плюс здесь может значить немножко разное, и по-разному это на процессоре будет вызываться, а обрабатываться. То а языки, а функциональные, то там система типов пошла гораздо дальше с самого начала. То есть на уровне типов можно выразить не только само физические констрейнты, но и что можно с этим делать, а какие свойства есть, где можно применять, где можно не применять. И даже для того, что у нас есть вещь, а с одного физического представления, сказать их, пожалуйста, не перемешивайте. Превращать в одно, в другое никак нельзя, даже кроме как злыми хаками. И это очень важно, да? То есть система типов сама, кстати, тоже сейчас отдельно поговорим, но помимо системы типов, именно сам вывод типов, он, конечно, функциональных языках в Хаскиле просто с самого начала. Хинли Миллер, все это знают, это выражение, на хабре есть хорошие разборы, если кто хочет почитать. И очень долгое время этого очень не хватало. Это же не было ни в одном мейнстримовом обычном императивном языке, правильно? Ведь вообще, по-моему, не в одном. И, конечно, именных языков. И вот тут скорее всего больше всех повлиял, конечно, это стали перетаскивать один из первых C#P очень долго шла к этому Java. Причём даже сейчас, когда там это есть, есть староверы, которые говорят: "Нет, так нормальный код писать не надо. Мы А, кстати, это привело к появлению inlay хинтов, когда у тебя в редакторе вар написано или там конст, неважно, но у тебя тип показан, хотя его, ну, нету в исходном коде". Хотя часть людей, конечно, всё равно жалуется, что в полреквестах ты этого ни хрена не видишь. Но я обожаю вывод типов, и мне очень больно было, когда я знал, что вот тут в Хаскиле люди пишут, есть, а вот здесь я пишустринг равнострингстринг стрингстринг. Вот меня это очень всегда бесило в джаве. Ну, естественно, современные языки, там гошка, ну, как соврешка, конечно, там древний язык, но всё-таки Гошка у тебя там А что у нас ещё этот, господи, как он называется? Typeesриpt. Угу. У тебя с этим добром всё совершенно прекрасно и хорошо. И даже более того, пошли ещё дальше, если тайпскрип посмотреть, когда у тебя там на типах вообще можно, а, напрограммироваться так, что мало не покажется. Код ещё более забористый, чем на Хаскеле может получиться, да, когда там на строчках видел, как разбираются строчки, да, когда у тебя ял файл превращается в тип. Это, конечно, круто. Это очень круто. К сожалению, на Хаскеле тоже такое сейчас можно написать в последних лет. А, уже можно. Серьёзно? То есть уже Typeскрипт повлиял на Хаскиль систему типов. Ну, здесь здесь сложный вопрос, кто на что повлиял. А, но в любом случае уровень вот этого программирования на типах и что мы можем выразить, он постепенно рос. И он улучшается в разных направлениях. То есть там в какой-то, ну, появились так называемые Type Families, грубо говоря, очень простые функции на типах, когда мы можем что-то выражать. А сначала это был про, считай, просто паттернчинг, потом уже мы стали способны что-то писать, потом поддержали уровень поднятия э строк на уровень типов, а потом и возможность их уже разбора и каких-то операций. Там уже именно в самом Хаскеле всё достаточно интересно, потому что здесь мы уже выходим практически на уровень языков с зависимыми типами. Мы хотим писать что-то на нормальном языке для рабо для работы с типом. В Хаскеле этого пока нету. в какой-то момент появится, но уже появляются какие-то подходы, которые позволяют решить часть задач. И вот, например, там, не знаю, одна из первых библиотек, которой была - это typesave в printf, когда у нас строчка в printf, вот этот паттерн, он разбирается на уровне типов, и, соответственно, это выражение принимает аргументы тех типов, которые записаны вот в этой вот строчке. Ну, естественно, известный статически в Хаскеле. В каком-нибудь Идрисе можно было радостно написать и где оно передаётся аргументом, и статически будет неизвестно. И как бы там компилятор заставят промчить типы, и если они смчатся, то тогда будет всё хорошо. Если нет, там придётся какую-то ошибку написать. Вот. Ну вот, заканчивая эту главу, хочется сказать, что в целом влияние функционального программирования и Хаскеля гигантское. почти всё, чем мы так или иначе пользуемся, любим и что мы ждали в обычных языках, пришло из этого мира. И только по этой причине уже, ну, можно хотя бы нормально относиться к этому, а не то, что там типа это никому не нужно, потому что оно происходит на фоне в высоких аудиториях университетов часто, да, где-то там, где мы этого не видим, но взрослые, серьёзные ребята этим занимаются. Так что спасибо ему за это. И смотрите, если мы с чем-то наврали, обязательно напишите, потому что мы так по памяти вспоминали. И что мы не сказали, тоже напишите, потому что это интересно. Понятно, что там есть ещё определённое влияние ирланга и Лиспов, кстати, во многом, потому что виртуальная машина, мы помним, тоже появилась в Лиспах там в шестидесятых ещё. А потом Java говорила, что она это чуть ли не придумала, но это так уже всякие интересные дополнительные штуки. Вообще, почему это интересно, но функциональщики как-то больше этим интересуются. Но по крайней мере эти штуки, они всегда циркулируют, потому что там пробуют из в мейнстримовых языках, конечно, с экспериментами люди боятся. Один из немногих языков, кстати, это, наверное, Нода, которая вот просто каждые полгода вбирает в себя всё, что знаешь, да, наверное, там каждые полгода новый выпуск, у тебя полностью скопировали пол какого-нибудь языка, и там люди вот просто бояться начали, что типа хорош вы что творите. И Java потом пошла по этому пути каждые там год или полгода новый ДДК, и люди начали тоже бояться: "Вы что делаете, остановитесь". Там же реально прямо фича, фича, фича, фича, фича, фича. Вот. А также, но в итоге просто хотелось, наверное, сказать, что, а, сейчас, наверное, в обычных языках так много втянули, что как будто бы вот прямо что вот нам очень не хватает, очень нужно и очень бы повысило производительность и так далее. Ну, честно говоря, уже сложно сказать. И мне кажется, что это одна из причин такого остывания как бы интереса к функциональному программированию. Потому что, несмотря на то, что сейчас мы в Хаскеле обсудим, есть невероятные вещи, в целом функциональное программирование, аэ, такого, чтобы ты прямо кардинально что-то изменил в своей жизни программистской, наверное, ничего не предлагает, кроме узких каких-то кейсов. Мне кажется, что здесь важно сказать, ну, то, что про что в последнее время много говорится, что такая штука, как парадигма программирования, функциональное, объектноориентированное программирование, процедурное программирование, оно превратилось уже в ничего не обозначающие термины. То есть его и выделять, что это функциональный язык программирования или это объектноориентированный язык программирования, большого смысла не имеет, потому что, во-первых, все концепции так или иначе в одной парадигме выражаются через другую. И как-то выделять, классифицировать, ну, это ничему не помогает. Все языки в современном мире являются мультипарадигменными. А раз все являются мультипарадигменными, что говорить об этом? Говорить о каких-то конкретных свойствах, не знаю, там, чистой по умолчанию. там стипизированной, нетипизированной, это всё ещё имеет смысл, хотя тоже не постепенно грани как-то стираются, потому что в тех же самых нетипизированных языках программирования появляются разные выводители типов, анализаторы там, а, хинты появляются, и это начинает прорастать просто везде. унификация сумасшедшая произошла за последние, да, годы, другие свойства, но всё равно так или иначе сейчас вот эти вот парадигмы, они интересны, на мой взгляд, максимум в теоретическом уровне. Если хочется почитать, откуда оно пришло, и если хочется взять просто какую-то, ну, это уже даже какие-нибудь учебные дополнительные языки, которые вообще нигде не используются, но можно найти на всяких там, не знаю, сервисах просто совсем исследовательски, где, не знаю, вырезано всё. Кроме того, что, э, минимуму просто посмотреть, как вот попрограммировать, как это будет работать, просто для своего интереса расширения способности думать э максимум. Так нужно понимать, что все языки, они уже становятся близки друг к другу и как бы нужно смотреть за что дешевле даётся. Вот. И что не ну долгие, да. Если говорить просто вообще про прикладную, конечно, ну, прикладное программирование, то тут, чтобы поставить жирную точку, конечно, речь в первую очередь идёт про экосистему. То есть языки плюс-минус все достаточно хороши. И там уже, конечно, сам язык мало что решает, если это не критические какие-то области, да, где реально нужно прямо раз воткнуть или там го или ещё что-то. А у тебя, конечно, речь идёт про твои фреймворки, там экосистемы, наличие инструментов и так далее. Ты просто там, как этот, собрал из готовых элементов, и у тебя всё получилось. Давай поговорим непосредственно про Хаскиль. Наверное, опять же, Хаскель в этом отношении отличается от других языков, а мне кажется, как будто бы потому что здесь надо говорить действительно про его фичи, которые очень мм очень необычные. Угу. Значит, мой личный опыт Хаскеля, когда опять же где-то году в двенадцатом, это вот вообще этот период вот этого повального увлечения для меня был с десятого пример по пятнадцатый год. Вот такой маньяческий, а очень сильный. И значит, когда я начал изучать Хаскиль, а, и хотел в х в Хекслет его засунуть. Кстати, мы хотели комалай утилитки на нём пописать, но в итоге отказались. А значит, я знаешь что сделал? Первое, наверное, что меня впечатлило после ленивости, то есть это одновременно с ленивостью - это корирование. Вот это просто ты, когда начинаешь вот -э работать на уровне чистого кода с просто с коллекциями, преобразованиями и у тебя возникает история частичного применения функции через э автоматическое корирование, это просто такой взрыв мозга. То есть мало что в моей жизни вот так вот на меня влияло с точки зрения вот в программировании, когда ты понимаешь, что тут прямо мозги вот так вот прямо тяжело даётся, чтобы вот это вот осмыслить. А когда ты это осмысливаешь и прямо видишь, что ой, а здесь зачем я это сделал? Тут же можно просто вот убрать всё это, да, оно там автоматом проваливается. Это одно из самых классных ощущений, которые я в своей жизни испытывал, когда вот программировал. То есть вот примерно экторы в Ирланге такое же ощущение рождали и в Кложе определённые штуки. Вот в Ирлан в Хаскеле для меня вот эта штука была, наверное, базовой, фундаментальной. Давай немножко про неё поговорим, потому что, мне кажется, это хотя бы минимум, вот прямо минимум, которым ты сталкиваешься в первую секунду работы с Хаскелем, который тебя уже как инженера, мне кажется, сделает лучше и покажет, что мир даже на таких маленьких штуках может быть совершенно другой. Ты вообще, наверное к этому привык, для тебя это норма. Да, я вот сейчас пытаюсь прикинуть, отобразить, как как я делал. Не, на самом деле у меня были, я бы не сказал, что это карирование, ну, то есть именно непосредственно с корированием, но в целом а вот построение некоторых пайплайнов работы, когда, не знаю, берётся мапа, она там об у нас берётся какой-нибудь список, мы это собираем в мапу, потом преобразовываем элементы, разбираем обратно и в итоге перестраиваем структуру. И вот такое возникало. И прямо иногда это было так-то. Вот сидишь и думаешь: "Вот у меня есть, я вытащил из базы", да? э из базы пачку данных, и мне их сейчас нужно отдать пользователю вполне понятному, соединив ещё с какими-то данными, которые у меня есть, но не а из той табличной формы, которая есть, а, грубо говоря, транспонировав. Ну, на самом деле, ещё с пачкой преобразования, там что-то досчитав. И отдать удобно для того, чтобы я вот у себя посчитал, а дальше, когда это там на фронт пользователю уйдёт, ему не пришлось бы самому всё это пересчитывать, потому что алгоритм три раза поменяется, и мне нужна единая точка, правда. Вот сидишь и думаешь это. И я прямо помню, я беру вот так вот листочек, кладу, ээ, рисую, что здесь вот у меня так оно преобразуется, получается вот такая вот диаграммка того, как оно преобразуется, куда идёт, и там какие-нибудь куча -пов, функ, там, все дела. Вот так вот сидишь на это смотришь, тратишь на это там 3-5 минут, а потом так всё вроде сошлось, начинаешь писать и оно работает. Потом даже уже начинаешь проверяешь в каких-нибудь там краевых сценариях, а дальше задумаешься, что очм как бы. И самое интересное, что на этом уровне ещё важен вывод типов. То есть когда ты пишешь, э, компилятор тебе не даёт даже сделать какую-то фигню, потому что, э, типы начинают не сходиться, оно начинает не работать. И когда вот испо И вот это вот было очень классно, это просто так радостно. Ещё вторая радость хаскилем - это опять же, я не знаю, еду из университета домой в электричке, мне нужно как написать какой-то код. У меня ещё тогда нету с собой ноутбука. Я беру листик и на нём просто пишу вот вот как-то там схематически ещё, как мне это нужно написать. Прихожу домой, кладу листик, тупо переношу оттуда то, что есть, и оно работает. Это это всегда то, что говорят про Хаскиль, да, то, что а как бы одновременные минус и плюс, грубо говоря, он тебе не даст запустить программу, пока у тебя не получится согласованная модель внутренняя. Но при этом, если ты сделал, то оно работает с первого раза, что не отрицает, что ты там плюс с минусом можешь перепутать, да, но типа работает сразу. Но если вот именно эту часть касаться, то, конечно, помнишь, тоже было много статей, как я с Хаски перешёл на Кложу, где как раз люди говорили, что, блин, она Хаским не даёт нормально поговнокодить, быстро что-то запустить, проверить. И многих людей это вымораживает. То есть тут уже какой-то личные предпочтения появляются, да, кто готов и кто так мыслит, а кто наоборот такой типа я тут пологировать легко хочу везде там что-нибуд позаписывать. Опять же Хаскилет же это даёт, но, ну, чуть посложнее, мягко говоря, это сделать местами. на на самом деле пологировать он на самом деле даёт в любом месте. Э и для этого вообще ничего дополнительного нету. Добавляется модуль debug trace, который позволяет как и в любом медическом коде, так и на самом деле в чистом коде, в любом месте добавить трассировку, увидеть логи, да, они будут не в том формате, в котором там стандартный логер выдаёт, если он в программе используется. Ну, потому что это будет отдельная как бы история. И, но самое сложное здесь, что если это написать в чистом коде, то чист порядок выполнения чистого кода может быть э совсем не тот, а чистого ленивого кода совсем не тот, который в голове есть. И, грубо говоря, понапихав в случайном месте логирования, возможно, в первый момент нужно при, ну, какое-то время, причём, возможно, даже продолжительное, придётся попонимать, откуда это происходит. Потом будет а-ха момент, после которого всё будет просто. И потом, не знаю, тае же логирование в энергичных языках, в строгих, аэ, приводит к тому моменту, а почему оно пишется. Вот это тоже у меня был такой момент, когда я отлаживал код на языке, э, который строгий. У меня там передано логирование, я логирую, что какой-нибуд какую-нибудь передачу аргумента функции. Ну, это язык такой весьма специфичный. Там дебагера в принципе нету. И сделать, чтобы дебагр был - это отдельная история. Поэтому а логировать можно. Поэтому я делаю так и и смотрю, начинаю видеть, что у меня вот выводится вычисление аргументов, потом вызывается функция. Я сижу и думаю: "А почему так происходит? Оно же у меня вот написано всё наоборот". А, ну, в общем, оно по после того, как привыкнуть к Хаскелю, это основная проблема, отвыкать будет сложно. А это основная проблема языка. Вот. Ладно, возвращаясь обратно, наверное, нужно вернуться к корьрованию, функциям и всем и всему такому. Давай я сейчас Да, я вот очерчу. Я сейчас понял, знаешь что? Потому что, смотри, когда мы говорим про Хаскель, всё-таки, несмотря на то, что там мы с тобой знаем и можем говорить для о той аудитории, ну, в такие видео часто приходит аудитория уже опытная, она хочет куда-то вот там далеко. Я просто извинюсь сразу перед всеми такими ребятами, что всё-таки хочется про Хаски на низком уровне немножко поговорить, потому что не как про другие языки, где можно вот в принципе там перспективы, работы и так далее. Хаскиль интересен не этим. И поэтому, поскольку у нас осталось времени очень много, давай мы про Хаскили потом ещё вот про Монады и всё остальное отдельно и теорию категории, и математику вот эту. А вот здесь мы остановимся только вот на этом базовом блоке просто, чтобы вот хотя бы заинтересовать тут. То есть мы берём с тобой, а, значит, порядок вычисления, ленивость, корирование, частичное применение функций и ну цепочки, когда у нас, собственно, как как-то, господи, функторы, аппликативные функторы, когда у нас, в общем-то, пайплайны мы строим безгу передачи функции и всего такого. Вот. Короче, мы вот этот скоуп берём, дальше не идём и только его, чтобы попытаться вообще описать людям, а что это значит реально на практике, чтобы они в голове картинку собрали. То есть, конечно, идеально, наверное, код было бы показать. Может быть, даже, кстати, мы сейчас сможем с тобой это сделать. А потому что, мне кажется, если мы хотя бы эту вещь сможем людям, а, объяснить и показать, это уже может прямо очень сильно повлиять на отношения, желание там попробовать и так далее. А потом мы можем сделать ещё дополнительные выпуски, в которых мы уже будем исходить из того, что эта часть закрыта. Давай попробуем так сделать. И давай, наверное, может быть, прямо покажем. Самая страшная история для меня, потому что я человек, который привык к тому, что я в консольке работаю. Это удобно только мне и показывать могу это только я. Это у меня там коллеги страдают на работе, когда приходят, спрашивают, как у нас работает это. Я говорю: "Не знаю, спросите хотя бы у кого-нибудь, я этим никогда не пользуюсь". Давай. Да, то, что тут реально надо прямо показать, да, мы такое прямо базовое немножко интро в HскиEL сделаем. Ленивость. Вообще это называется нормальный порядок вычисления. Хаскель в этом плане очень интересен, и он отличается, наверное, практически от всех существующих языков, но он один из уникальных, но как минимум самый популярный среди таких. Это когда действительно аргументы, передающиеся функцию, вообще ничего не вычисляется до тех пор, пока оно не нужно. А мы, например, в обычных языках к этому привыкли, как правило, либо у нас есть даже такой паттерн, там ленивая инициализация, аа это часто в стримах используется, в джаве в той же самой, это в дополнительных библиотеках или в языках, когда коллекции обрабатываются, когда вы строите цепочку и если это не цикл или то оно сразу не вычисляется, да, оно потом вычисляется, а какие-нибудь бесконечные коллекции, генераторы, которые по чуть-чуть отдают, это вот всё примерно вот туда же. Только в Хаскиле - это по дефолту работающий язык. Вот так работает. И это очень сильно влияет на то, как работает код. И для того, чтобы эта штука работала, там ещё должны выполняться некоторые требования. Второе функциональность проявляется в том, что у вас порядок вычисления. Вот то, что сейчас Саша говорил, это, возможно, может ломать мозг и, а, создавать очень странное ощущение от происходящего. О том, что у вас порядок вычислений может быть очень разным, в зависимости от того, что когда будет нужно. То есть речь идёт не о том, что вот вы вызвали функцию, она вычислилась, а оно будет вот где-то потом эта цепочка вычисления будет раскручиваться в момент использования этой штуки. И это как бы с одной стороны даёт возможности много оптимизировать, с другой стороны немножко усложняет понимание, когда вы не всегда осознаёте, в каком порядке что вычисляется. А почему, например, порядок в целом может меняться, а в, например, в обычных языках меняться он не может, потому что в обычных языках у вас есть зависимость изменения состояний, изменения переменных и так далее. Здесь это такая типичная история функциональных языков, когда у вас а нет такой зависимости, поэтому порядок вычисления может меняться. Это там позволяет параллелить лучше, ну и много чего другого. Опять же, есть оборотная сторона, тут Саша про это лучше скажет, что такая ленивость, она местами создаёт как раз наоборот потребление памяти безумное, когда оно м раскрывается не так, как нужно. А я тут на практике с этим не работал, потому что я не специалист в Хаскеле. Саша про это расскажет. И ещё одна часть, которую мы сейчас вот разберём - это корирование, частичное применение. Значит, корование - это когда у вас, то есть так, частичное применение, когда у вас есть функция от трёх аргументов, а вы вызываете её с двумя аргументами и, соответственно, остаётся как бы, то есть вызов её с двумя аргументами порождает новую функцию, а минус эти аргументы. Это на лямбдах можно очень легко сделать. Это действительно бывает полезно сегодня. Сейчас вот мы вам прямо покажем, как это работает. А корирование - это когда функция от n аргументов превращается в функцию n функцией по одному аргументу. Ну, например, когда у вас была там, не знаю, сум и она принимает там два числа, которые суммировать. А теперь представьте, что сумма принимает одно число, а возвращает следующую функцию, которая принимает ещё второе число, и, соответственно, происходит вычисление. То есть это выглядит как сум один, потом ещё одно вызов, как два таких вызова типа там два и сумма, сумма даёт три. А это может выглядеть как теоретическая конструкция, но вы увидите, что когда это встроено таким образом язык, это позволяет, а очень стандартные вещи, с которыми мы пользуемся в нашей жизни, а писать намного проще, удобнее и красивее и компактнее, чем это происходит в других языках. То есть намного меньше использования лямд, намного меньше всяких оборачиваний. У вас код, ну, как правило, часто приводит в пример. Вот показывает HKEL код и другой код, он Haskill код намногонамного чище в этом плане выглядит. А, и опять же повторюсь, это не в каких-то спецситуациях, это прямо вот на минимальном уровне, где идёт обработка коллекций. Саш, вот, кажется, я дал введение. Да, я, наверное, готов. Так, ну я в любом случае начал с простого. То есть, наверное, самое такое явное, вот что сразу в голову приходит, как увидеть применение корирования, там, где это прямо реально вот мозг ломает, это банальный список чисел, который с которым мы что-то делаем, да? То есть, например, список чисел, к которым, например, допустим, мы к каждому числу должны прибавить десятку. Вот простейшая задача. Не будем её оборачивать ни в какую прикладную штуку. Она покажет концепцию. Дальше будет понятно, как это использовать. А в обычном любом языке, как это выглядит? Мы делаем маap, в котором передаём лямдочку, в котором получаем параметром текущее значение, и мы складываем. То есть получается, я думаю, в голове все примеры себе представили. Если что, может быть, сейчас напишем. В Хаскиле это будет выглядеть по-другому. И так, как выглядит в Хаскеле, такого, ну, можно сказать, вы, наверное, скорее всего, не видели наверняка, если на нём не писали. Так, поехали тогда. А то, да, что-то думаешь, так говорить про Хаскель для людей, которые вообще не представляют и на словах пытаться объяснять всё это, а, мне кажется, очень плохо работает. То есть нас будут на это интересно будет только тем, кто и так с этим как-то знаком. Так, поехали. Во всяком случае, то, что я не не верьте, что у всех эскилистов также плохо настроены идшки. У них всё хорошо настроено и хорошо работает. Вот, соответственно, у нас будем писать код внизу будем видеть всё, что изменяется практически сразу. А, и напишем простую функцию, которая, а, как Кирилла и предложил, прибавим к списку каждому элементу по десяточке. Только шрифт давай сделаем чуть побольше. Да, давай. Это не туда. Вот сюда. Так. Так. Нормально. Да. И я только единственное вот чуть подсказывать буду. Ты пря с мапа начал с ходу. Давай прямо сначала прямо определим просто список, чтобы у людей так это последовательно эти конструкции в голове были. То есть да, прямо с определения начнём. О'кей. Сейчас, секундочку, это запустим. А у тебя, кстати, это VS-код, что ли? Я просто Да, код. Я я сейчас перелез на VS-код. Там, на самом деле, для тех же хаскелей всё хорошо. Там интеграция сDE, Энжайном и всё такое, оно более-менее работает. Супер. Вот. А, соответственно, возьмём список.
Угу. Вот так вот. Сходу, если расширение не видеть, пока выглядит как А, ну давай там почти любой язык программирования.
сраз так вот это печатается, да? Да. Не, на самом на самом деле вот это вот, то есть что у меня есть наверху это код, внизу у меня просто интерактивная штука, а которая видит изменения в файлике и запускает этот файл. А так на самом деле в таком виде я с ней не очень люблю работать, поэтому
поэтому я могу лично с ней тупить. Так, всё отлично. Ну опять же, тип можно было не писать. Это, да, тип, тип можно не писать. Это я сейчас поскольку здесь у нас и вот вот эта вот история, я только делал так, чтобы для неё было удобнее работать. для Дешки, да, даже не для дешки, а для внешнего внешней утилитки, а которая которую я запустил в консольке моей дешки. То есть можно радостно это использовать с и безешек. Вот. А, собственно, так. Дальше мы хотим к этой функ.
Сейчас нюанс. Давай, чтобы на сравнении, можешь комментарий поставить и показать, как это выглядело бы, а, ну, допустим, там в любом языке типа джаваскрипта. А когда мы пишем, поставь комментарии mylist. Map, не прямо mylist.map, а здесь Угу. Понятно это нель скобочка. Ещё раз скобочка ещё раз скобочка. Да, ещё раз скогурная обычная, да? X, да. И вот X п 10. Вот это 99,9% э языков выглядеть будет примерно так. Теперь смотрим на то. Сначала напишем, а потом объясним, потому что это да, здесь здесь даже мы сделаем как-нибудь, не знаю, там const.
Угу. Так будет, соответственно, чтобы что чтобы уж одинаково писать совсем. Да,
в данном случае это будет так. Можно проверить.
Кажется, похоже на правду. Очень похоже. И вот я, когда я первый раз столкнулся, ребят, надеюсь, что вы испытываете эти же эмоции. Ты смотришь такой, думаешь: "Это вообще что?" То есть вроде никаких спецсимволов нет, как обычно Хаскель, когда показывают, да, когда там ты выглядишь какие-то символы. А что это такое? Вот давай поговорим, потому что это просто база баз вообще того, как работает. Мы сейчас включим просто интерпретатор для того, чтобы даже интерпретатор на нашем файлике, для того, чтобы сюда что-то можно было вводить, смотреть. Соответственно, если мы посмотрим, наверное, посмотрим, что такое функция плюсик и, э, и её тип, соответственно, плюс, мм, ладно, не будем усложнять жизнь. А-э, на вот эту вот часть пока смотреть не будем, но, грубо говоря, оно говорит, что это число, а дальше оно говорит, что это функция, которая принимает два аргумента и одно какого-то типа, который является числом, и возвращает третий аргумент возвращает значение того же типа, что вполне себе соответствует нашему обычному пониманию от того, какой тип у плюс должен быть. А, Саша, давай прямо покажем, да, на примере именно вот не не как тип, а вот просто потому что, смотри, я сейчас объясню, почему 100% такой вопрос возникает у людей. Мы же не вели понятие, а почему это плюс и типа это что, лисп. Это же не совсем лисп в этом плане, да? Давай чуть раскроем по поводу префиксной постфиксной аннотации и того, почему плюс - это функция, а не просто оператор.
То есть в Хаскиле плюс - это функция, но но его можно записывать как 1 + 2, но при этом это функция, да, вот про нотацию такую.
Так, сейчас думаю, как лучше сказать. Ну, о том, что по сути у таких функций, грубо говоря, есть просто особый синтаксис языка, который позволяет, ну, это прямо встроено, короче, в язык, что у тебя встроены вот эти функции можно использовать посередине. Это то, но это не операция, это на самом деле функция. Ну, это пишем 1 + 5, да, для Ну, у нас для всех функций, которые являются префиксно, то есть, не знаю, там писать что-нибудь такая штука и прочее. Всё, что является символами. Соответственно, они, как они называются-то? Они пишутся между операторами. 2три, да, там есть особое название какое-то у них. То есть фактически это просто синтаксический сахар, но по большо, да, что-то типа такого инфикс, но по большому счёту это функция, да, да, это просто обычная функция. Соответственно, у неё есть тип, и для неё всё работает как для обычной функции. При этом в Хаскеле, на самом деле, это уже упрощённый тип. И на самом деле этот тип выглядит как
если расставить скобочки, он выглядит вот так. А, соответственно, это на самом деле функция на самом деле кориирование, что это функция, которая принимает один, то есть мы можем считать не абсолютно корректное утверждение, но но в простом уровне мы можем считать, что все функции принимают один аргумент и возвращают всё остальное. То есть мы можем рассматривать плюс как функцию, которая принимает один элемент, который работает как число и возвращает новую функцию, которая будет принимать один аргумент и возвращать число. То есть, например, если мы посмотрим посмотрим тип плюс вот для вот так вот плюс единички, то это будет снова функция, которая принимает один аргумент и возвращает число. Соответственно, если мы к этой шту эту штуку применим ещё к одному аргументу, то это уже будет просто число. Ну и можем присматривать. А, да, давай посмотрим. Не на типах именно, а то, что А ты можешь убрать вот скобки вот вокруг плюса самого? Да, могу. Ну, на самом деле, это просто так будет понятнее всего. Да, мы давай опять же длянятности сделать алиа, то есть сделать функцию сум, которая равна функции плюс, и заодно, кстати, показать, как это работает, и прямо с функцией с этой функцией показать, собственно. А, да.
Вот давай теперь пока. А, ну просто я уверен, что с с непривычки людям тяжеловато будет типы, поэтому я скорее сейчас про то, что нам лучше показывать прямо прикладной код. То есть безпов, то есть мы можем вот так написать. О'кей. Да. То есть а то есть это фактически, то есть у нас тоже надо сказать, смотрите, давай покажем настоящий вызов, чтобы люди понимали. В Хаскеле не ставятся запятые, в Хаскиле не ставятся скобки. Из-за этого так выглядит. Ну прямо покажи со скобками, чтобы с запятыми, чтобы прямо выглядел как обычный код. Тогда мне, то есть я могу сейчас заставить это работать, но это уже чуть-чуть сложнее, потому что это уже у нас, а вот это вот выражение тритри 3п5 скобочка закрывается, это уже у нас кортеж из двух элементов. Соответственно, это штука такого типа. Поэтому, если, да, да, ну, мы скорее говорим о том, что, а, вот это то, что мы сейчас делаем, это то же самое, что вот как бы в другом языке выглядело бы так. Просто оно, несмотря на то, что, знаешь, это удивительная вещь, то есть у тебя символов как бы меньше, обычно же люди что боятся, когда у тебя больше странных символов и ты их не понимаешь, а у тебя здесь всё знакомое, символов меньше, а работает как бы так же, как ты ожидаешь, да. Поэтому я хотел этот сравнение показать, чтобы люди понимали, что происходит здесь, да, и как бы А теперь мы можем показать, вот ты начал набирать, собственно, что любую функцию можно вызывать в середине, если она принимает два аргумента, правильно ведь? И делается для невстроенных это делается с помощью амперсандов, да, собственно, такая история, что можно применять,
да. Вот. А уже сейчас я думаю, что если кто-то, слава богу, смотрит нас и внимательно пытается понять, что происходит, уже, наверное, охренел, как на базовом таком уровне Хаски кардинально отличается от всего, с чем люди до этого работали. И что самое смешное и самое классное, отличается абсолютно в позитивную сторону. Символов меньше, возможностей больше, минусов нет. Ну, если так вот сходу посмотреть, да, ровно так. Поэтому все вот эти вот функциональные истории с различными редюсами, с суммированиями, проходами, они становятся очень простыми. Ну, например, не знаю, если а мы не объяснили, прости, да, давай. То есть я сейчас всё, что мы с тобой рассказывали, ты извини, что перебил, но просто мы же с тобой не показали, что происходит. Мы с тобой как бы подготовили людей, а вот МАП +10, собственно, давай теперь покажем. А, собственно, что такое +10-то? Да, теперь возвращай, собирай всё вместе. Самое важное, если работаете с Хаскелем и будете смотреть и тип, он вам скажет практически всё. То есть, если возникают вопросы, сначала смотришь тип, потом думаешь, а работает отлично. Соответственно, +1 - это функция, которая принимает аргумент э чего-то похожего на число и возвращает результат того же типа. А, соответственно, если мы посмотрим на MAP, это всё работает как обычно, как в более стандартных привычных языках. Это функция обычная, которая принимает два аргумента. Один вот такого стрелочного типа, то есть функцию, второй список элемента вот такого, как первый параметр. И возвращает как результат. Таким образом, если мы в MAP подставим сюда, мы можем прямо прикинуть, что если вот это вот окажется вот здесь, то есть здесь будет аа. Всё нормально. То есть эта штука уйдёт, и у нас будет функция, которая принимает список типа А и возвращает список типа А. Проверим себя на всякий случай. Вдруг будет правда. К счастью, правда. А, ну, единственное Б, ну, это уже отдельно. Соответственно, это штука, которая будет каждому элементу прибавлять десяточку. И теперь, если мы ему сделаем my list, то получим и тип нам не нужен, да? То есть фактически, а я попробую сейчас другими словами сказать, чтобы поняли, потому что я всё равно как меньший хоскелист чувствую, что у тебя, знаешь, этот уровень понимания, он сильно выше и люди, которые с этим незнакомы, могут немножко протормаживать, угонять за твоей мыслью, да, что по сути у тебя МАП принимает на вход сейчас два аргумента. Первый из которых это функция собственно преобразователь - это классический колбк. Собственно, вот как в четвёртой строчке. То есть вот этот вот x x + 10. На самом деле это оно, но оно из-за того, что у вас функция по дефолту корирована, написано +10, то есть применился первый аргумент. И вот такую штуку мы вернули. И она на вход. А и дальше передаётся myли list, который фактически идёт вторым параметром. То есть у нас получается первая - это функция, в которой +10 уже зашито. М и my list. И соответственно дальше, а давай покажем прямо применение этого +10 к первому элементу списка, просто чтобы увидеть, что внутри происходит. Хорошенко переменные. Ну прямо +1 можем написать вот так вот + 10 и дальше скобочки, чтобы или так не не сработает. Сейчас если мап вообще убрать, если мап убрать и просто взять первый элемент списка, вот прямо чисто ручками это показать, да, вот вот эту логику. Ну да. Ну и, собственно, вот таким образом внутри чуть выше было тоже, да, да, передаётся. И, кстати, и давай тогда последнюю, чтобы прямо совсем замкнуть, если для тех, кто до конца всё рано не уловил, мы с тобой П10 можем присвоить функции, присвоить прямо функции и передать её в map, да? Вот mapA функция list.
Вот. И вот вот так начать применять и делать. Это тре, ну, то есть ты прямо переосознаёшь очень сильно вообще всё, что происходит, потому что часто бывает, я думаю, ты через это тоже проходил, когда только на Хаскиле начинал писать, ты пишешь вот эти длинные конструкции, а потом понимаешь, что у тебя куча лишних передач, и у тебя всегда код на Хаскиле в конечном итоге вот он начинается, допустим, 20 строк превращается в пять. Ну а потом ты вообще знаешь, что функция zipwave сделает всё за тебя. Да, это в самом конце. Вот. Но в любом случае есть такой переход,
да, собственно. Не знаю, можно ещё какой-нибудь zip показать, который хорошо работает и показывается. То есть у нас, например, если нам нужно, у нас есть список, нам нужно два списка объединить, мы можем их объединить в, а, каждый элемент с каждым и функция zip, которая объединяет их в пары. Соответственно, первый с первым, второй со вторым и так далее. А, соответственно, есть функция zipвид, которая применяет, принимает себе функцию, которая работа, которая Сейчас посмотрим, пока ты пишешь, которая понимаеш, да? А, ну ладно. Я просто думал ты сейчас писать будешь. Я просто хотел сказать, что многие, кто это видит сейчас, они, наверное, узнали и вспомнили, что у них в языках есть что-то типа аля_oreладаша и так далее. И это как бы прямая калька как раз тоже с этих всех функций, которые вот пришли из такого более математического математической истории. И да, это популярно стало. Причём, кстати, в Хаскеле всё это встроено, ну, в стандартную библиотеку, а в большинстве остальных языков это не является стандартной. Библиотека - это расширение почти всегда. Ты знаешь ещё хоть один язык, в котором это стандартная либо из популярных? Ну, я уверен, что ребята из Сишарпа скажут, что ли, наверное, что-то подобное делает, но в целом, в целом нет. Не знаю, где прямо стандартная. Ну, в принципе, на самом деле такое уже появляется везде, где оно появляется в библиотеках, которые не дани нестандартная библиотека, но где-то рядом. И как бы каждый, кто работает, он знает, что оно есть. там какие-нибудь фанктуулсы, что-нибудь, фанк, что-нибудь оно будет называться и лежать пачка всяких таких историй. Ну, на самом деле, всякие вот эти зипы и прочие в языках типа Раста, они там везде близко и в коллекциях обычно функции плюс-минус так и называются. А давай покажем ещё с фильтром, просто чтобы у нас был ещё один пример. А давай найдём все чётные, например. Давай. Найдём себе чётные в каком-нибудь большом списке. Чётное - это у нас even, кажется, да? Угу. Вот, соответственно, достаточно просто, что если опять же, чтобы посмотреть, что здесь происходит, можно пойти по очереди, по типам, смотря, что это происходит. У нас функция фильтр принимает два аргумента: предикат из того, э из какого-то типа в булево выражения и список этих самых выражений. И, соответственно, возвращает список. А если прочитать документацию, то будет, соответственно, список для тех, для кого предикат выполняется. Ну и функция even - это функция, которая говорит чётное это или нечётное значение. А, понятно, что функцию even писать не всегда хочется. Можно вернуться к старому. Давай напишем, покажем пример. Да, да, да, покажем пример.
А это, кстати, вот, чтобы вы понимали, на Хаскиле нормальная абсолютно лямбда, вот полноценная, собственно, как это и сделалось бы в любом другом языке. Вот оно всё есть, выдаёт похожен тот же результат. Естественно, можно записать, поскольку мы знаем, что у нас есть корирование, есть всякие стили, можно тоже выражение записать немножко в более наркоманском стиле. А так, чтобы здесь X не было и он бы полностью ушёл. Но я не думаю, что это разумное решение и, наверное, так делать не надо. Но у меня есть дальнейшая штука. Вот опять же, а если бы в других языках, например, работали с бесконечными списками, да, им нужно было бы, ну, аля что-то типа генератор использовать. Теперь, да, я как раз хотел переформулировать. Давай возьмём, что как будто у нас есть бесконечный список, и мы говорим, что мы также его фильтруем, но мы хотим взять первые 10 числ чисел из этого списка. Можешь вот написать эту конструкцию, и дальше мы тоже её поясним, потому что прикольно. Да, сначала сделаем, что вот вот конструкция будет такая, и она обработает этот бесконечный список за быстро. Но сначала я покажу, что список всё-таки достаточно бесконечный, потому что если я это не возьму, то он вот будет вычисляться, вычисляться и так достаточно долго, учитывая, да, именно так, что пока не закончится память. Причём, пока не закончится память на конкретный элемент, а не на весь список. Так что это ждать придётся достаточно долго. Угу. Вообще то, что ты сейчас показываешь, ребят, хочется подчеркнуть, насколько это безумно красиво и круто. Это не какие-то дополнительные штуки. Это не отдельные, как в Питоне вот генераторы есть прямо отдельная штука. Это прямо является частью языка на базовом уровне. И посмотрите, как оно нативно. Вот говорят такие: язык, который читается как текст. Чем вам не язык, который читается как текст? Но тут м помимо того, что сейчас ты сделал, есть и вторая суперважная вещь, которую я всегда очень люблю приводить в пример тем, кто привык к ОП. Знаешь, обычно есть какая проблема? Люди, когда в обычных языках пытаются писать на функциях, у них получается очень странные и страшные конструкции. То есть, если ты делаешь, например, Mapфilter Reduce, используя аля link там стримы, у тебя классно и красиво, да, там коллекция, точка MapA, точкафильтр, тра-та-та-та-та, да, там есть проблемы, иногда бывает, когда посерединке что-то надо вставить и так далее, но в целом это красивенькая такая цепочка получается, если они в своих языках, и я думаю, что большинство разработчиков так себе это видят. О'кей. А если я буду писать на функциях, как эти хаскилисты, у меня же ужас получится, потому что у тебя как бы вот эта цепочка в ложности сделает так, что тебе надо изнутри смотреть, что происходит. И каждое оборачивание приводит к ка. То есть это физически неприятно, неудобно и так далее. Из чего делается неправильный вывод? Что с функциями работать неудобно. А правильный вывод, у вас нету хороших конструкций, которые позволяют с этим работать. И тут мы приходим к этому символу, который ты не пояснил. И мы сейчас поясним. доллар, что же он означает и почему это так важно? И, кстати, покажи альтернативу, чтобы люди это видели, да? Потому что то, что ты показал, это же не обязательно так, да? То есть можно показать как обычный вызов, да? доллар, э-э, если не удаляться в его магические функции, которые у него тоже есть. Но это если мы будем делать такие
ээ встречи и рассказывания про Хаскиль, дойдём к десятой и одиннадцатому месту. В общем, если это убрать, то это просто замена скобочек. То есть, грубо говоря, мы это оператор, который принимает два аргумента. Слева стоит функция, которая применять, справа значение, как к которому её применить. И это всё. Никакой магии. Можно считать, что это самая обычная функция, такая же как любая другая. И мы её можем сами определить. Например, сказать, что вот мой доллар, который берёт функцию и значение и применяет функцию к значению. И написать
это на всякий случай, чтобы показать, что всё, что в Хаскеле вот здесь происходит, здесь нету абсолютно никакой магии. То есть это не специальный синтаксис, не расширение компилятора, ни что-нибудь. Это просто обычные функции, с которыми обычный язык работает как обычно. Даже несмотря на то, что символ доллара, да, доллар символом специальным не является, в отличие от какого-нибудь двоеточия, с которым так просто не поработаешь. Вот. Ну я бы, наверное, добавил, что по сути это аналог. А тут есть ещё как бы обратная штука, да? Есть же ещё и в другую сторону. То есть это в прямую сторону есть, есть ещё в другую сторону. Мы можем либо взять из стандартной библиотеки,
естественно, я всё так напишу. Вот. И, соответственно,
Угу. сказать вот так вот в прямую сторону, и у нас всё будет работать, что мы вот пофильтровали и потом применили действия. А доллар был исторически раньше. В стандартной библиотеке амперсант появился очень не сразу. Ну, это аналог какого-нибудь символайкалайна, да, появился сильно позже. И разные варианты пайпов, они стали активно использоваться, когда стали в Хаскеле появляться стримы. Это в отличие, вот здесь мы всё смотрим чистый код. То есть все как бы мы, если мы говорим, что вот этот вот список его делает генератор, то он чистый. Здесь не подивляется никаких спецэффектов, а стримы - это штука, уже позволяющая работать с эффектами и делать всякие интересные вещи с ними. Я бы здесь вот прямо сейчас ещё показал один пример и сказал, что по сути а вот этот вот функтор, вот эта операция - это у нас замена пайплайна в других языках и ��амена стрелочки или точки в объектах. Давай прямо покажем пример, чтобы люди поняли, что когда у тебя есть такой механизм, у тебя супер удобно всё писать. А я бы по-другому сделал. Давай начнём, знаешь, прямо как, чтобы прямо видно было. Мы берём бесконечный список, а находим в нём только те числа, которые больше десяти. Нет, стой, нет. Давай берём бесконечный список, где в каждому числу прибавляем десятку. Вот то, что мы здесь сделали. Потом берём только чётный, потом берём только первый 10. Вот все операции, которые мы сейчас делали, да? Тут, конечно же, у людей возникнет вопрос: "А как вы вообще понимаете приоритет?" Ну, потому что особенно у рубистов же тоже там скобок нету. И у тебя бывают проблемы из-за того, что вот ты, когда так пишешь, типа, а что является аргументом и какая функция к чему применяется? Ну, здесь всё просто. Зде, ну, вопер есть приоритеты и и на их более-менее можно помнить, но в целом, на самом деле, всё достаточно очевидно. Можно знать, что доллар применяется самым последним. Всё, всё, всё, что после он съест и всё. В общем, я, если честно, их никогда не помню. следах. Да. А про про доллар про доллар можно помнить. Я я на самом деле фанат скобочек во всех местах, в которых это возникают хоть какие-то вопросы. Здесь, ну, лично для меня вопросов никаких не возникает. Приоритет применения функции достаточно высокий. И здесь как бы всё понятно, что амперсанды разбивают. А вот я даже, кстати, не знаю вообще, ребят, вот кто видит сейчас эту строчку, а мне интересно, напишите, пожалуйста, какие вы испытываете эмоции. Мне кажется, что вот люди делятся на несколько разных типов по отношению к тому, когда они это видят. Меня это настолько впечатлило и мне настолько это понравилось, что речь вообще даже не о прикладном использовании и так далее. Мне просто вот как некоторые фанатеют от лидкода и любят там на те решать задачки, мне Хаскиль вот этим так запал в душу. И самое главное, никто кроме него такого не даёт, что только ради этого я там на нём реально какое-то тратил время, решал такие задачки и получал неимоверное удовольствие от того, как это всё пишется. А потом, когда возвращался на любой другой язык, я такой: "Э, мне немножко больно от этого". Хотя, наверное, кстати, Кложа одна из немногих, в которых за счёт макросов можно частично повторять эту логику, но там всё это, конечно, нетипизировано и может больно быть. Вот, кстати, здесь написано это, что это инфиксный оператор слева объединяет и, соответственно, оно будет всё, что слева объединять, таким образом разбивать. Примерно как у доллара, а у него нолик приоритет и в правую сторону. О'кей. Вот как мы теперь можем посмотреть на Ну, я бы тогда две вещи, да, мы ленивость хотели посмотреть, насколько это теоретически мы сможем. и патроно. Ну, на самом деле, ленивость мы здесь посмотрели, потому что вот как раз тейк 10, оно работает за счёт ленивости. А как её мы можем посмотреть? По сути, ну, это, во-первых, самый простой пример. Во-вторых, мы можем посмотреть, написать какой-нибудь ербom. Это штука, которая, будучи вызвана, и скажет, что всё взорвалось и всё плохо. Таким образом, мы узнаем, что оно было вычислено. То есть, если мы, например, сделаем список и захотим его вывести,
то вот как только начали его выводить, вот здесь мы начали выводить список, у нас появилось его начало и появился дальше exпtion, бум, все дела. И даже лучше, чтобы лучше это увидеть, давай присвоим, чтобы увидеть, что оно не выводится, если мы просто присваиваем его, да, к чему-то, да. А теперь мы попробуем, ну, например, просто присвоить, а вот, ну, здесь ничего. Вот, если попытались вывести, проблема. Дальше. Теперь вопрос, когда это вызывается. Например, мы хотим вызвать какую-нибудь функцию, которая работает со самим списком как со структурой. Например, длину списка взять. Норм история. А, проверили. Вот там длина пустого списка ноль. одного из одного элемента единичка. А что у нас даст на нашем иксе, который говорит бу? Мы взяли и посчитали. То есть это значит, что в тот момент, когда мы работаем с этим списком, а вот то, что здесь было значение тех элементов списка, они, в принципе, не вычислялись. При этом мы прошлись по всему списку, узнали его длину и ничего внутри не вычислили. А в любом другом языке хотел сказать, что пришлось бы использовать лямды для того, чтобы это не произошло, и потом работать с этим как с функциями. А может добавить, наверное, пару слов про оптимизации, потому что, например, кто-то мог бы заметить: "Слушайте, ребята, но если у вас плюс как функция, а мы смотрим на small Talk, там же это всё супер было неоптимально, как это всё работает". А, и в Хаскеле, насколько я понимаю, тут я уж совсем не специалист, несмотря на то, что функция как плюс, как абстракция работает в коде, на низком уровне-то там всё очень неплохо оптимизировано. То есть даже многие вещи, которые как функции, это не будут у тебя там нагромождение тяжёлых операций. Там очень много сложных историй, много оптимизаций. В общем, самое главное, что язык компилируемый, язык с оптимизирующим компилятором. Соответственно, он очень много чего сделает для того, чтобы сделать так, чтобы всё работало эффективно. А, соответственно, все маленькие функции, которые, ну, действительно маленькие по некоторому определению их размера, которые компилятор присвоил маленькими, он сохраняет помимо в интерфейсный файл, а, помимо всего исходный код. То есть, грубо говоря, и если вместе использования маленький функции, он подставит туда её определение. Дальше таким образом он, ну, почему пайплайны хорошо работают, соответственно, и дальше он существует много правил перезаписывания. Грубо говоря, это как раз единственный момент, наверное, где входит настоящая математика, который делает преобразование над структурой данных и превращает одни функции в другие. Соответственно, таким образом он позволяет не создавать дополнительные промежуточные структуры. То есть на самом деле в коде, который мы видели выше, вот с этим, аэ здесь не, на самом деле, здесь ни в одном месте не создаётся ни одной промежуточной структуры данных. И ни в каком месте не существует ни бесконечного списка, ни здесь бесконечного изменённого списка, ни вот этого двох проходов проходов, да, не то, не то чтобы двойных проходов. Сама самой структуры нету. На самом деле это на всём уровне, э, это превращается в один большой генератор, который выдаёт значение. Причём, если мы их потребляем, не собирая в список, а просто, например, все выводим. Мм, не знаю, там print.
Вот. Ну, мы мы, к сожалению, я не поставил ограничение, вот, то на самом деле в памяти всегда будет только одна, только один элемент GTфункция, которая генерирует следующий. Вот за счёт этого и за счёт очень больших оптимизаций того, как мы работаем. То есть, грубо говоря, если у нас есть корованная функция, у нас будет одна ссылка. Ну, даже пусть у нас плюсик наш не оптимизируется, это есть примитивная операция, на которую есть ссылка, то мы в структуре, в памяти создаём структуру, где собираем все аргументы и потом её применяем. Соответственно, у нас не будет алоцироваться объект лямбда, а у нас просто будет собираться данные, и это будет работать весьма эффективно. Там, на самом деле, есть некоторые интересные моменты с этим, но я боюсь, что я не уверен, что я правильно их сформулирую, просто не перепроверяя. Но это очень круто. То, что ты показываешь очень круто, потому что опять же те, у кого ёкает, кто с этим работал, понимают, что тебе, а там, где особенно поддержки в языке нет, это вообще нереально просто так сделать. А там, где есть, у тебя всё равно нужно использование специальных штук. Либо какие-то встроенные генераторы, либо там тебе нужно их самому мутить. Естественно, у тебя там всё будет создаваться. А, но в общем, это целая, короче, история. И это, прикиньте, ребята, это только списки. Мы говорим только про самую-самую базу языка. Это даже мы не не как бы не пошли во что-то более серьёзное, сложное. А чуть-чуть добавлю тут, что, хотя мы смотрим, вот мы плюсики, минусики, логичный вопрос возникает: "А зачем мне это всё надо знать?" И я вот пишу реальный продакшн, который перекладывает Gсон из базы данных в клиента. Ээ и где мне это там будет нужно? На самом деле возникает и действительно нужно. То есть, ну, если с каким-нибудь мэпом всё, э, достаточно понятно, то, например, все эти же истории могут быть, я не знаю, мне нужно пронумеровать результаты, там мне нужно, а, собра, у меня есть где-то параметры, а здесь есть рядышком лежат результаты, которые вернулись, мне их нужно объединить, а здесь мне нужно, э, сделать группировку. Вот мне пришли пришли результаты из базы как плоской таблицей, и мне нужно сгруппировать их по определённому ключу, а потом пофильтровать и и найти интересное. Вот все вот эти операции, они они собираются вот в такие пайплайны, из которых всё можно собрать. И очень-очень много задач можно решить на основе базовых историй. А когда они выражаются в основе базовых историй, то у вас автоматически тест coverage, потому что вы используете не что-то своё, что я написал, а потом я начну работать над другим проектом, на мой придут три других человека, которые уже не помнят, кто чего писал. Оно делается на основе общих историй, которые знает любой человек, который работает с языком, просто потому, что он не мог мимо них пройти. Ну что, давай покажем паттерн матчинг. Сможем показать? Да, наверное, можно с паттерн матчингом. Вот мы сейчас воспользовались списком как такой структурой, то есть готовым. А я предлагаю сделать какую-нибудь историю и написать какую-нибудь историю типа поиска длины по списку или суммирования в предположении, что никаких списков у нас нету. И там как раз будет паттернматчинг и подход к нашей задаче, что тоже важно в Хаскеле, поскольку у него есть алгебраические структуры данных. А неважно, почему алгебраический хороший способ. Слушай хотел, блин, я хотел следующим вопросом к этому прийти. Смотри, может быть, тогда мы с этого начнём. Я вот хотел и паттерчик, и алгебраческие структуры данных, потому что про них важно поговорить. Я бы начал с них, потому что паттерн мачинг тогда очень явно подходит, а ещё используя стандартные красивые слова, которые используются и в других языках программирования, алгоритмах и прочем. Вот, например, мы введём наш список, задекларируем структуру данных. Сейчас подумаю, как. Э, если мы говорим про наши структуры данных, которые есть, то мы можем сказать, что у нас, я сейчас специально буду использовать не математические, нехальные простые термины, то у нас есть два варианта. У нас есть либо структура данных, в которых есть несколько полей, либо есть структура данных, которая у которой есть несколько вариантов. То есть у нас и вот эта вот штука у нас у нас или А, или B, или у нас есть и А, и B, и C. Вот. А, соответственно, в Хаскеле декларирование структур данных, которые используются, строятся вокруг этой системы. То есть мы можем говорить, что у нас, например, наш, что такое наш список, э, наш список - это или элемент. Так делать, ладно. Это у нас элемент, а дальше мы можем сказать и какой-то список ещё дальше. А, то есть вот так. О, извини, я тогда, знаешь, что понял? Нам наверное самый классический пример, который имеет смысл сейчас показать, потому что это будет с этим связано, это с вычисление факториала с матчингом по функциям, когда у тебя, а, ноль и когда у тебя или единичка, я забыл уже, как там, да, у тебя факториал единички и факториал такой. Ой, сейчас подумаем. Ну, може, помнишь, когда у тебя, ну, это просто самый, наверное, простейший пример, а, этого паттернматчинга, именно когда у тебя функция без ифа раскладывается на аргументы по типу а или стой, подожди, пустой список. Нет, тут не список. Я сейчас ещё с сортировкой. Ну, у тебя на факле есть простого сейчас. Вот, в общем, тут мы сделали, то есть таки таким образом мы сделали single linked list. У этого кода есть сейчас одна проблема. Список, который мы написали, он получается бесконечный, потому что вот у нас есть список, и у нас каждый элемент - это список ну, текущее значение и продолжение его какой-то ещё, э, список. Соответственно, чтобы это, а, он когда-то терминировался, мы должны иметь какой-то хвост. Вот. Соответственно, таким образом получается, что структура, список у нас - это или текущий элемент с хвостом, или хвост или с продолжением, или всё, терминировались, конец. Вот у нас есть такая структура данных, не самая эффективная, не самая быстрая. У неё там линейный поиск по ней. А, но мы можем так хранить данные, можем проверить.
Так, у меня там где-то был наверху myли list, поэтому мы его закомментируем, чтобы он нигде не мешался. Вот. И вот так напишем. Make list
5
6.
Можем так написать. Учитывая, можем написать ещё более красиво, но будем писать так. Так, проверим. Да, нам нужно, чтобы он умел показываться. Такая магическая штука. Мы говорим, что мы его можем распечатать. Так, и посмотрим, что нам скажет наш Myлист. Вот. Ну, вроде всё похоже на правду. Красиво, хорошо. Дальше, если и основной очень важный принцип работы в Хаскеле, и чем это круто, это то, что когда у нас структуры записаны таким образом через алгебраические типы данных и через э или и, а, соответственно, мы можем многие алгоритмы делать стандартным через стандартный паттерchн, то есть когда мы, грубо говоря, проходим по нашей нашей структуре и проверяем все варианты. Например, мы сделаем наш My L, который должен посчитать длину списка. Соответственно, он берёт список на вход и возвращает чиселку.
Вот как мы можем работать. То есть я человек, который не представляю, а как это делать. Я смотрю на свою структуру. А у меня есть два варианта, которые могут быть. Я так сразу и пишу, что в том случае, чтобы, я не знаю, можем как функцию написать, можем сразу через какой-нибудь кейс для того, чтобы у нас был паттерн матчинг прямо как кейс. Слушай, а паттерн матчинг на кейс, понятно. А на самих функциях можно? Через на самих функциях, да? Ну, в смысле, вот здесь, когда ты тип описываешь, да, в аргументе и у тебя просто несколько, как они клоз, вспомнил, они в ирланге клозами называются. Да, можно, можно, естественно. Я здесь как раз спросил, как комфортнее. Я именно это имел в виду, когда про факториал говорил, да.
Собственно, вот так. То есть у нас есть два случая всего. Мы их разобрали, других нету. Если мы вдруг что-то забудем, компилятор нам скажет, что мы не очень хорошие люди.
Так, make
так. С вт
не хочет.
Во, ээ, всё сразу же сказал, что у нас паттерн мачинг у нас не покрывает все варианты, и мы ещё забыли покрыть. Тут единственное, чтобы всё-таки люди не потеряли нить, о чём вообще идёт речь? Речь идёт о том, что, а, поскольку, грубо говоря, давай вот в двух словах объясним, да, что когда ты вызываешь эту функцию на этом типе, а у тебя и ты определяешь, э, грубо говоря, вариант вызова, то у тебя должны быть это вот вот эту конструкцию, её надо осознать. Вот типа ты несколько раз записываешь одну и ту же функцию, это выглядит как перегрузка функций, но это не перегрузка функций. А давай вот это вот объясним сначала, потом уже скажем, да, по поводу забыли, не забыли, как это работает. То есть это это не перегрузка функции, потому что у неё один один и тот же тип, и то, и другое. Так что поэтому это не перегрузка. Что здесь делае что здесь происходит? Здесь, а, при выполнении мы сверяем, совпадает ли тот значение, которое нам передали с тем образцом, который у нас есть. И в случае первого совпадения мы вызываем правую часть и, соответственно, то, что там происходит. Ну не в значении для Хаскеля будет неправда, что мы его вызываем. Мы возвращаем вот это вот значение и всё, оно там дальше когда-то вызывается. А вот и таким образом мы, э, при исполнении мы проходим по всем вариантам, которые мы задали, находим первый подходящий и вызываем его. А, соответственно,
я знаю, что надо добавить ещё, чтобы было понятно. Это очень, то есть фактически мы реализуем такой мэтч, который сейчас реализован во многих языках уже вот перетащили его, где у тебя приходит значение, в зависимости там от типа оно разбирается. Только тут не от не от всего типа, а от элементов, грубо говоря, типа. То есть потому что тип - это либо одно, либо второе, либо третье, да? То есть вот мы каждое либо одно, либо второе разбираем. То есть воспринимаете это не как разные функции. Это это просто синтаксический способ записать одну функцию таким образом, чтобы внутри не делать ифов по типу или матчи кейсов, в зависимости от того, какая у вас в языке реализация. Это опять такой очень красивый сахар, который можно, конечно, было бы и по-другому сделать. Вот поэтому это просто определение одной функции. На самом деле аналог свеча от сде сделать что-то другое вполне себе можно. Есть стандартный этот кейс. Ладно, я уже пишу с расширениями, но если писать без расширений, будет кейс X of и, соответственно, вот, то есть это просто конструкция для любителя, когда когда что удобнее, то есть в некоторых историях, например, если здесь будет миллион текста, то вполне возможно кейс будет удобнее работать, а чем вот, но миллион текста лучше не писать, а, в любом случае. Вот, соответственно, у нас есть два варианта. А, и здесь всё опять можно вспомнить математику. Всё это становится очень похоже на, а, доказательства по индукции, на вот всю вот эту вот работу. Ну, на самом деле, это кейтип. А вот, ну, и, соответственно, что такое длина? Вот если у нас список пустой, то длина у нас, понятно, это ноль. Что такое, если у нас список не пустой? Ну, во-первых, нам не нужно, нам не важно, какое значение. Это мы знаем, что это единичка плюс длина того хвоста, который у нас будет. Просто по типу смотрим, пишем вот примерно. То есть, если я буду объяснять какому-то человеку, как бы я считал длину односвязного списка, я бы сказал: "Я беру голову, запоминаю единичку и смотрю длину оставшегося списка и считаю её. возвращаю результат длины оставшего списка плюс один. Собственно, как я это говорю, так это будет записано в коде и возможно будет работать. Да. Ну так. Ну здесь уже люди, которые не привыкли к рекурсе, конечно, наверное, чуть сложновато будет, но в целом не надо пытаться, может быть, даже это сильно понять. Это просто классическая рекурсия. Я бы даже уточнил, что это рекурсивный процесс, потому что можно ещё и по-другому, да.
My lens и передадим Myлиist 2. Похоже на правду, да? Ну, для сравнения, наверное, опять же, чтобы это было понятнее, конечно, имеет смысл самим реализовать хоть раз такой список в вашем языке и односвязный, и просто вы увидите, насколько будет, э, скорее всего больше кода и будет сложнее та конструкция, которую вы напишете у вас. Вот. А пока Кирилл говорил, я факториал уже факториал переписал. Да не к тому, что я ещё подчекнул то, что может показалось, что мы какие-то такие фанбои, любители Хаскеля. Ха, речь не идёт совершенно речь не идёт совершенно о том, чтобы тащить это в продакшн и типа так писать везде код. Речь просто идёт о том, что этот язык, он как бы даёт такие выразительные возможности и другой взгляд на мир, что имеет смысл его изучать просто для того, чтобы по-настоящему расшириться в понимании и программирования, и подходов, и всего остального. И потом, кстати, гораздо проще уже понимать в обычных языках, кстати, когда туда начинают всякие мэтчи вносить, когда начинают всякие: "А зачем мне карирование, а зачем мне то, зачем мне сё?" Хаскель очень в этом помогает. Поэтому мой поинт всегда был, не могу Саше не сказать, что Хаскель - это всегда история про то, что вы как инженер, если растёте, то к вашему основному языку есть набор языков, которые включают в себя хаскель, который позволяет вам стать более лучшим инженером. Вот. Потому что я знаю, что сейчас будут накидывать типа сидите тут на этот на ваш хаскель. Не, ну на самом деле, а здесь достаточно понятно, что у нас, э, большая часть разговора не об этом была, но в целом, если разворачивать всю вот эту вот историю, это достаточно важное свойство для языка и для решений. И если, программируя даже не на Хаскиле думать об этом, то качество решений может повыситься. То есть, грубо говоря, что что самое важное, что мы здесьделали, что мы определили структуру данных. И во многом структура данных может повторять процесс, решения, которые мы делаем. И, а, перечислили возможные варианты, которые там есть. А дальше весь код, который мы пишем и который у нас происходят, а он строится практически автоматически. То есть мы просто идём по той нашей структуре описания проблемы, которая есть, э, и пишем решение. И автоматом получаем то, что оно полное. Все варианты проверены, всё есть. А, и ещё все эти истории достаточно удобно объединять, э, как раз вот с помощью всяких пайплайнов, а, применения функции. И всё это дружит между собой, потому что как бы это база дизайна языка. Вот. Ну, единственный, наверное, самый сложный момент для того, чтобы вот с ходу это ухватывать- это, конечно, рекурсия, потому что всё, что здесь делается, оно очень сильно на неё завязано. А если её, ну, не практиковать и у вас не было опыта такого, то я подозреваю, что большая часть того, что сейчас мы объясняем, она, конечно, требует, короче, сесть и с листочком это поделать. Вот я боюсь, что напишите, кстати, ребят, очень интересно, насколько понятно, нет, а успеваете выслями или нет, и вообще можно ли просто слушать этот подкаст или только смотреть.
Здесь, кстати, интересно. Проблема, основная проблема может быть в том, что уже выработались привычки, потому что для людей, кто не изучал программирование, не смотрел и часто хаски, ну, удивительно, просто заходят. А, и когда люди сталкиваются с рекурсией как с первой вещью до каких-нибудь циклов, а до решения способов её выразить по-другому, это очень хорошо заходит, потому что на самом деле, ну, очень часто в той же самой школе, когда это было давно и неправда, и первый раз мы сталкивались с доказательствами по индукции, мы радостно использовали рекурсию, никогда об этом не задумываясь. А когда мы её потом через много лет встречаем в коде, это начинает пугать. Хотя, кажется, а это одно из самых, один из самых простых способов доказательства себе, что что-то работает, но и не только себе. Я, да не поверишь, на Хекслете это проходил, потому что мы же были очень хардкорные в те времена, там семнадцатый год, мы учили по сикпу и мы учили людей сначала рекурсий и только потом циклом уже после того, как они научились вот вот это всё делать. И это было реально круто, потому что я это в не просто в школе, а на взрослых людях обкатал и знаю, что это так работает, как ты сейчас говоришь. Им реально проще. Они потом многие относились к циклам, ну, даже с недоверием. Но, конечно, под давлением, так сказать, общественности и общих тенденций нам пришлось это убрать. Но это не отрицает того, что всё, у нас это осталось. И я очень хорошо вот прочувствовал на большом объёме людей, как реально классно это работает. Когда они вот так начинают мыслить, это сильно прямо помогает. Но не заставишь людей современных это делать, если они идут сами учиться программированию. Да. Ну что, давай посмотрим теперь факториал, потому что нам очень похоже. Я на самом деле заменил факториал на произведение, потому что я что-то, пока мы говорили, подумал, что факториал всё-таки работает от чиселки и возвращает чиселку, и там никаких списков нет, поэтому там всё-таки дано, а или можем обычный. Так что я здесь сделал произведение сначала, а теперь можем вместе и факториал сделать, соответственно. А
фактори, а ты хотел использовать свой собственный список, а я просто на числах хотел показать. Да, дада. Да. Соответственно, сейчас сделаем факториал честный на чиселках и сделаем то же самое. Чиселки, на самом деле, в этом смысле не сильно отличаются. То есть у нас есть база нолик, а следующая чиселка - это у нас, ну, так, да. Ну, тут не бу не буду делать natural. Предположим, что отрицательных чисел не бывает и всё хоро А нет, мы мы на самом деле сдела Ладно, вот сейчас сделаем отрицательные числа следующим шагом. Вот здесь, на самом деле, можно воспользоваться очень красивым n + k паттерном а и написать вот так. Это было в книжке не помню уже чей. И это расширение было сделано исключительно для книжки. Но мы так делать не будем. Ну это, да, это выглядит, конечно, уже магически. Ну вот что классно здесь показывает, то, что у тебя матчинг происходит не только по типу, но и по значению. То есть у тебя фактически Ну я здесь внесу свою корректировку. Вот вот здесь вот матчинг тоже по значению. У нас тип один и тот же. Матчинг по типу мы написать можем, но мне кажется, это стоит делать не сегодня и поговорить много о чём до этого. А потому что вот вот вот это вот это разные конструкторы одного и того же типа. И в этом смысле циферка нолик или n, оно ничем не отличается от makeist и make list new. Это просто разные конструкторы одного и того же типа integer. А что здесь новое появилось? Это то, что вот здесь мы сравниваем с конкретным значением, а здесь, то есть, мы не смотрим на структуру типа, а на структуру значения типа. А здесь мы мэтчим его с конкретным значением. А здесь мы говорим, что вот всё подряд нам подходит. Ну, всё оставшееся, да? Да, всё оставшееся. Вот, соответственно, мы можем проверить факториал шестёрочке. Что-то там у нас посчитается нолика посчитается минус единички и уйдём надолго ждать, потому что он идёт в мину1. Так и будет идти очень долго, пока у меня есть оперативка. А нет, к оверфлоу. Прекрасно. Кстати, я понял ещё раз вот эту штуку подчеркнуть, да, что вот здесь по сути вот верни, пожалуйста, обратно вот вот эту строчку, да, хотел именно сказать, что справа-то это а штука, ну, по сути, это определение функции, это тело функции, если сравнить это с обычными языками. Потому что, я думаю, вот эта история, когда ты просто написал равно и у тебя никаких слов лямбда просто выражения, это требует прямо реально привыкания, потому что с Хаскиль вот на этом уровне он чем поразителен, у тебя символов меньше используется, у тебя меньше конструкций, но но смысла больше. И вот это фантастика, по мне для таких вот штук. Сейчас ещё чуть-чуть добавим одну. Да, Гарда,
мне лень писать нормальные ошибки, поэтому там хорошие люди должны написать что-то разумное вместо ох. Ну уж как же живём. Вот можем запустить. Вот нам сказали ох со стек трейсом того, где это вызвалось. Естественно, пытливый смотритель может заметить и сказать, что мы почему-то проверяем это выражение на каждом вызове. И, наверное, это не очень логично, потому что когда-нибудь мы упадём сюда, если на первом выражении мы это не сделаем, ну, не попали сюда, то должно быть всё хорошо. Поэтому для того, чтобы сделать жизнь таких людей лучше, мы это сделаем. Мы чуть-чуть перепишем код. Кстати, вот интересно. Я вот не помню, в Хаскиле можно так писать, когда у тебя просто по гардам разделение идёт. Хм, наверное, можно. Я так давно не писал, что уже даже забыл. Да. Ну, в смысле, можно можно у каждого выражения сделать гарды. Не, я имел в виду, что у тебя при с одним и тем же параметром вот, да, можно, конечно, наверное, да. Просто не знаю, почему у меня это из головы вылетело. О'кей.
А я сейчас подумаю, как это разумнее написать. Вот так вот не ждали, не гадали и получилось, что мы в итоге лайфкодем показали по Хаски. Может быть, это даже даже будет класснее.
А там глядишь и я я не знаю, на самом деле зачем я переусложняю, но мне что-то это нравится. Я ещё я ещё стандартные конструкции напишу. Вот. Поэтому те, кто знают алгоритмы и делают всё правильно, это не ругайте меня. Вот. Но во всяком случае, это будет честно. Итого. Сейчас проверим, что всё работает. Теста я, естественно, писать не буду. А-э, всё прове проверили, что-то работает. И лишних сравнений у нас нету. То есть у нас в случае, э, одно лишнее сравнение, но переживём. можно написать, будет больше кода. Ээ, просто я представил, как я это напишу, и понял, что мне придётся слишком много объяснять, если я напишу так, как я это люблю писать. Вот тут есть ещё такой нюанс, о котором нельзя сказать. О то мы такие как классно, прикольно, да, это всё классно, прикольно, но действительно, если начинать по производительности разбирать, то эти штуки могут просаживаться. И поэтому фактически код, который ещё и производителен, часто чуть-чуть менее симпатичен, чем если бы мы это в лоб писали по красоте, как вот было сейчас. Согласен с этим выражением на самом деле. Да, да, согласен. И а особенно, если это в каких-нибудь очень важных историях там вылезают необходимость знать о том, как это работает внутри для того, чтобы писать хорошо. На самом деле, в большинстве случаев, если просто написать наверху, а language strict data и следить немножечко за тем, как пишешь, и не вызывать функции, которые никогда нельзя вызывать, или language strictт ещё более, но это я уже не очень люблю. Это переведёт в режим, когда язык будет работать сильно более строго, чем обычно. И это решит, на самом деле, 90% головных болей. Вот там просто есть истории, которые со стандартным программированием, как на Хаскиле, могут работать хуже в этом случае. А вот, но да, есть такое дело. Код может начать, там могут появляться всякие смешные символы типа восклицательных знаков везде подряд. Там появятся всякие истории типа там, не знаю, LED mштрих равне
иштри умно n восклицательный знак. Что-то, да, очень быстро наша красота может начать распаливаться,
да, будет будет уже не так приятно или там или ещё хуже, когда этих восклицательных знаков не было, могло быть что-нибудь типа вот так, что будет значить примерно то же самое, но ты уже сидишь и не представляешь, что это значит, смотришь какие-то смешные символы, секи, как мы это, в общем, эта штука говорит, что перед тем, как мы вычислим вот это вот, мы должны вычислить вот это вот. А то есть тебе приходится теперь явно управлять порядком иногда, когда язык по дефолту, ну там всё равно не совсем явный порядок. Там появляется это зависимости. Да. Дадада. Кстати, классика для всех описательных языков. Возьми там Docker compose, возьми Kubernetis. Да, у тебя везде это есть. Если у тебя декларативный язык, у тебя 100% есть механизм зависимостей. Да. Вот, причём нужно говорить, что такое слабая нормальная форма. Нормальная форма, что значит, что мы вообще вычисляем. Когда появляются свои данные, нужно понимать, а до какой степени мы вычисляем, что мы там добавили какой-нибудь лишний кортеж или maybe. И мы и мы можем понимать, что наша стандартная вот эта вот штука вычислялка, она уже больше не будет работать и вычислять до нужного уровня. В общем, в языке есть. А-а, если начина, если не зная язык, сесть писать -э высокопроизводительный сервер, причём, наверное, не веб-сервер, а какой-нибудь, который прямо данные передаёт, потому что для веб-серверов есть фреймворки, которые за тебя это решают. Вот если это начать сидеть и писать и не знать этих историй, то можно ворваться в проблемы и столкнуться с тем, что ничего, всё работает медленно, не так, как ожидается. Особенно, если влезать в какие-нибудь очень красивые штуки, которые все говорят, что вот там, не знаю, вот используйте очередную систему эффектов, у вас всё будет классно, прикольно, вы всё отлично сделаете, а потом окажется, что она на какой-нибудь истории, которая неожиданно оказалась именно вашей, тормозит и там какое-нибудь квадратичное замедление и всё. А, соответственно, такая проблема есть. Поэтому, если вдруг вы начинаете писать на хаскеле важный продакшн и важная история, убедитесь, что в команде есть кто-нибудь, кто это знает или готов изучать со старта. Это как раз вот подтверждает ту историю, что Хаскиль до уровня понимания идей, концепции для того, чтобы обогатить свой арсенал, быть более лучшим инженером, есть граница, на которой это останавливается, и тебе уже нужно, ну, в каком-то смысле бороться с языком, и это не добавляет тебе каких-то очков с точки зрения твоей крутости инженерной. Это просто уже специфика хаскиля и знания вот конкретной экосистемы. Вот где-то вот этот водораздел есть, потому что я не думаю, что вот эта штука она, а, ну, есть, наверное. Я здесь согласен, потому что, ну, вот знать вот эту вот историю здесь, кстати, не совсем корректно, но в новае направление знать, это не обязательно. С другой стороны, а во всех, наверное, экосистемах есть некоторый водораздел, когда для дальнейшего написание эффективной работы с системой тебе нужно знать, как оно внутри живёт и что это такое. В общем-то, я не знаю, во всех направлениях, в которых, э, работал когда-либо, всегда оказываешься в варианте, что тебе нужно знать кишки. И то, что не делает тебя лучше, как, ну, не знаю, на самом деле, я считаю, что это делает лучше как программист. Просто когда тебе нужно написать что-то похожее или столкнуться с этими вещами в других языках, ты уже что-то знаешь. И на, на мой взгляд, лишних знаний не бывает. Главное - это не пихать их куда не следует. Вот. Да. Ну, тут скорее речь про то, что именно особенность Хаскеля и его позиции в этой штуке, что его можно воспринимать один из немногих языков исключительно как вот а некий теоретический базис там или какие-то конструкции, которые тебе действительно помогают, и в принципе на этом останавливаться, потому что продакшн на нём писать, ну, маловероятно, кто будет, и доходить до такого уровня тоже маловероятно. Но если вы дошли и пишите, то вот будьте готовы, что со всем этим, конечно, придётся разбираться. И то, что в одном месте делает вам хорошо й, да, в другом месте вам придётся с этим побороться. И с этим действительно сталкиваются многие. Вспомни, вот TheOps в этом плане вообще, мне кажется, прекраснейший пример, потому что там или, кстати, Ормки, который тоже помнишь вот эту историю про Ормки, когда ты сохраняешь в хибернейте, и ты не знаешь в каком порядке, что там вычислится, потому что оно там само зависимости считает и так далее. То есть вот с этой точки зрения это знать надо, потому что я считаю, что это вот как раз такое понимание, ага, императивно или декларативно? Декларативная штука. Значит, там по-любому ленивые вычисления, значит, там зависимости должны быть, значит, управляется не тобой. Соответственно, ты сразу понимаешь, неважно, ты работаешь в Реакте, ты работаешь в Хаскихле, ты работаешь в в этом, господи, как они там называются, кубернете, да? Угу. А ты понимаешь, что проблематика одна и та же на самом деле, и она связана не с инструментом, а вот именно с этой ээ концепцией вычислений. Правильно ведь, наверное, так назвать это, да? Порядок вычислений. Есть истории, когда порядок исключений и то, как оно, а, происходит, становятся важны для решения конкретной проблемы и реализации. И во всех декларативных историях здесь будут дополнительные сложности. Вот. Да, в общем, я не знаю, я бы здесь был SQL прекрасный пример, да, да, SQL и как это пытаются с ним решать для того, чтобы это сделать, и как разные кома и как разные сервера подходят к разному к таким пожеланиям, которые стараю, некоторые стараются чётко банить и говорить: "Используйте всегда декларативна база о вас позаботится и если не заботится, заводите баги". или наоборот, где мы вам дадим возможность типа написать с сколько угодно хинтов для того, чтобы превратить это в императивную историю. Вот. А не знаю, я чуть-чуть позащищаю Хасль здесь и вернусь. То есть я бы сказал чуть-чуть осторожнее, что если вдруг по какой-то причине вы решили использовать HCL в продакшене, убедитесь, что вы понимаете, какие по какие последствия могут быть и как это будет работать, потому что, ну, не знаю, лично в моей практике, а, писать продакшн на Хаскиле легко, удобно и приятно. И, а, в большинство проблем скоростью, с поведением, с тем, как оно вы, э, как оно вычисляется, не столкнёшься, если следуешь простому набору правил. Далее следует простой набор правил, который бывает, а, разные люди публично говорят, бывает в докладах. Ну, и, соответственно, все они выглядят, в общем-то, разумные. И если какое-то время потратил на изучение языка, их уже более-менее будешь знать. Но с другой стороны, если вдруг не готов, если команда никто, ни у кого нету практического опыта, работы и работы с языком, а успешного опыта или рядом нету какого-нибудь человека, который всё это объяснит, то это большой риск. Я не знаю, вполне возможно, это верно и для любого другого языка программирования, ну, для многих языков программирования, но для технологии, кото в которой ты не профессионал, есть риски. Здесь они возможно больше. Вот зато если их обойти, куча плюсов есть. Саш, тебе большое спасибо, что ты пришёл и поделился и всё это показал. Я надеюсь, что ребятам, которые смотрели, это было полезно, и это не просто разговор о Хаскиль, а вот возможность действительно была прикоснуться и хотя бы какие-то идеи уловить уже на практике. Мне кажется, что мы сделали правильно то, что мы не стали абстрактно говорить там про реальную прикладную разработку, потому что, ну, хаскин не тот язык, о котором можно просто говорить про разработку, не видя и не зная вот этих вот базов��х вещей. Поэтому, ребят, если вам понравился выпуск и то, что мы таким подём пошли, поставьте, пожалуйста, нам лайки. Если их будет достаточно много, я уверен, что я Саше уболтаю, и мы, например, сделаем ещё один выпуск, потому что как минимум потому что все, когда про Хаски говорят такие: "Там же Монады, ребята, где это всё есть и почему вы это нам не показали". Это просто штука, она в чистом коде, ну, можно сказать, не появляется особо. Она появляется именно тогда и в там вообще без этого никак, когда у вас появляются побочные эффекты. И, соответственно, это отдельная большая как бы тема. То есть как бы Хаскиль даже с точки зрения изучения это два разных две разных истории, да? Вот я как бы в первую очередь эту изучил, а на второй я сломался. То есть я её частично начал, но я такой понял, что всё, дальше я не могу. И вот эти все трансформеры, там очень сложные какие-то штуки, они, конечно, требуют дополнительных усилий. Поэтому, в общем, если вам интересно и хочется продолжить, я бы отдельно сделал выпуск по обработке ошибок варианта исключения там монады и побочные эффекты разобрал отдельно. может быть, параллельность, не знаю, пока. И, например, допустим, в теории потом уже можно там поговорить прямо прикла про прикладной код, вот прямо реальные проблемы, реальную историю и всё остальное. Так что зависит от того, как вы лайкаете наше видео. Но если вам не понравилось и вы считаете, мы слишком его залюбили и он того не стоит, поставьте дизлайк и напишите тоже что-нибудь плохое, мы читать всё равно не будем.
Вот. А так, Саш, большое тебе спасибо. Было приятно пообщаться. Спасибо, что пригласил. И спасибо всем, кто послушает и напишет что-нибудь. Да, всем пока.
