Это копия, сохраненная 13 февраля в 04:34.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Т.е. ты сможешь шлёпать своё авторство, но только под BSD-3 или аналогичную лицензию. Я хочу полностью выкупить этот код и сделать его open-source. И, разумеется, я хочу взаимодействия. Т.е. у меня есть хотелка для создания либы, но сам я не потяну, у тебя есть возможность её написать.
Деньги обсуждаемы. Я думаю, 50к - это просто хуйня, которую я выбрал от балды. Если надо поднять, то поднимай. Если это гораздо больше стоит, то так и пиши, что тебе это не интересно, но заодно напиши, за сколько денег ты готов работать. Не факт, что у меня столько есть, но мне чисто интересно.
Изучаю F# после многих лет поедания императивного говна на с++.
Потом планирую вкатываться в хаскель.
Пока самый большой вопрос у меня возникает в том, что как обрабатывать ошибки, кроме возвращения из всех функций optional ( Maybe в хаскел ).
Но такой подход кажется довольно сложным, т.к. приходится биндить все следующие функции к предыдущей и непонятно в каком мементе там зафейлится, либо каждую функцию делать принимающий optional и в каждой функции проверять вход, что тоже довольно геморно.
Как вообще делают товарищи хаскелисты в продакшен коде?
Тот который не попадает в множество пет проектов.
Как и в любых языках: если эта ошибка "нормальный" результат функции - то Maybe или Either, если кровь-кишки-распидорасило - то кидай исключение.
>>171797
Ну и если "ошибка" - это "нормальный" вариант, но подразумевается, что программист не должен постоянно проверять результат функции, а есть какой-то стандартный паттерн обработки такого результата (например, fail-fast для Maybe или бэктрекинг для монадического парсера), тогда или пили монаду вроде Monad Maybe, если она для твоего типа ещё не запилена, либо трансформер, если хочешь дать программисту выполнять какие-то еще монадические действия между биндингами.
Но именно к ошибкам вида "кровь-кишки-распидорасило" это не относится. Конечно, можно эмулировать систему исключений на трансформерах, но это ничего не даст. Потому что в языке уже есть исключения, причем даже асинхронные исключения, поэтому в продакшн коде всё равно придётся это учитывать и писать обработчик исключений. Т.е. даже очень чистый воображаемый ErrorT ничего не даст, один хуй, исключения придётся ловить.
Главное, не используй исключения для нормального flow-control. Тут как и в любых других языках: исключения - это именно что исключения. Они возникают когда что-то идёт не нормально, они должны случаться редко. И поэтому они медленнее, чем неглубокий монадический биндинг (но быстрее глубоких стеков трансформеров), и главное, они проще в использовании.
Если они тебе нужны, сразу юзай safe-exceptions либо исключения из unliftio, либо из RIO для конечных приложений. В исключениях из base есть некоторые грабли, как раз связанные с тем, что бывают асинхронные исключения их надо очень аккуратно обрабатывать.
Ну а если твои исключения - это не исключения, а норма, тогда монадка, да.
Да он просто поржать пришел, я уже понял, что никому это не интересно, сам пишу. Хотелка одна - быстрее malloc и не зависеть от malloc, потому что хуй знает, что там на разных платформах вкомпиливается под видом malloc. И да, интересуют только 64-битные платформы. Так-то я уже сам начал потихонечку его писать. Вернее тесты производительности пока, чтобы понять глубину пиздеца с malloc и всякими примитивами Хаскеля.
А, переписываешь jemalloc на хачкиле. Похвально.
По сути, должно быть несложно - прост тред-сейф связный список свободных блоков.
jemalloc вроде тоже может под 32 бита работать. На 64-х битах можно еще сильнее ограничиться по выравниванию, ограничить переменную под размер блока 48-битами (один хуй нет столько памяти в компьютерах), а старшие, например, использовать для сохранения номера арены. Немного пожертвовать фрагментацией, создавая free-листы только для степеней двойки и использовать битовые операции вместо красно-черного дерева для поиска списка. Еще заточить под мелкие объекты (16 байт, у меня, скорее всего, таких много будет), ну и никто не заставляет повторять интерфейс malloc. Вместо мьютексов использовать спинлоки. Я не смотрел, что именно используется в jemalloc, но в классическом malloc есть мьютекс, это правильно с точки зрения ОС, но если подразумевается, что на серваке будет только моё приложение, то можно и в спинлоке покрутиться. Ну и количество арен и подобное сделать настраиваемым. Все эти универсальные маллоки пытаются быть очень умными и подстраиваться под любой характер нагрузки. А если сделать тупой аллокатор, который надо настраивать вручную, то может получится выиграть в скорости за счет его тупизны. И за счет отсутствия foreign call немного.
>ограничить переменную под размер блока 48-битами
Очень плохая идея, даже ядро процессора не знает как там адресное пространство мапится на физическую память, это дело mmu, а в конце адресного пространства обычно стек, 0xF...F и ниже.
мимокресты
Звучит как план
Причём тут это вообще? В этой переменной должен храниться размер блока, для этого не нужно больше 48 бит, в оставшейся части можно хранить доп. информацию.
Потому что полезные фичи оттуда пиздят в практические языки.
Мне математики сказали, что в хаскеле нет категорий. Зачем тогда хаскелисты о них постоянно говорят?
Просто будет на что опереться. Ну типа расширяет границы сознания, в итоге ты сможешь решить какую нибудь задачу так, как никогда не решил бы, если бы не знал функциональщину. Я не тролю, у меня самого так было.
Вот так всё говорят, какими-то абстрактными словами о том что ФП добавляет в кругозор новые взгляды на жизнь и это охуенно, ты будешь мегапиздатым, но я так и ни разу не видел реального примера из жизни.
А должен понимать?
Собственно, интересует, есть ли более современные альтернативы STG или прикольные/полезные улучшения, не включенные в GHC?
Например Maybe такой не является, если x : Maybe A, то x >>= f не всегда вызывает f т.к. x может быть Nothing.
Анон, насоветуй может есть какие-нибудь мастрид статьи, не слишком тухлые, по концепциям кложи/ФП. Может какое-нибудь сравнение ФП языков с императивными языками. Чтобы объективно и интересно.
stack
НУ смари, ты хоть знаешь что такое ленивые вычисления? Нет? А знать надо, потому как в популярных императивных ОО другая система вычисления, это тоже знать надо. Если бы ты изучал хачкель хоть немного, то уже бы не задавался таким вопросом. Всё очень просто.
Ну и как, много написали?
Ленивые вычисления, это когда что-то вычисляется только тогда, когда это действительно нужно. Абсолютно бесполезная ерунда, короче. Да и к тому же во время исполнения все это в любом случае транслируется в императивный ассемблер для аппаратной платформы. Хаскель это литералли мем, чтобы просто ньюфагов троллить. Как Gentoo.
Что за хуйню ты пишешь, если у тебя все функции могут возвращать ошибки?
Ну чтож, поведай нам как ты ТОЛЬКОВЫИГРАЛ!!1! от того, что у тебя система обновляется по несколько часов, а то и дней, изнашивая процессор постоянной загрузкой на 100% и заставляя тебя засыпать под шум вентиляторов.
Не надо нищебродских проекций, на моём рузене полная пересборка вообще всего установленного займёт часов семь, обновления обычно занимают час-другой по субботним утрам.
> изнашивая процессор
Мало того, что ты нищеброд с медленным железом, ты ещё и тупой. Процессор от 100% нагрузки не изнашивается, максимум, что от этого изнашивается - это подшипник в кулере, который стоит три тысячи рублей, но куда тебе три косаря сэкономить на завтраках.
> пересборка вообще всего установленного займёт часов семь
А, ну это совсем другое дело (нет).
>Процессор от 100% нагрузки не изнашивается
Ещё как изнашивается:
https://yarchive.net/comp/linux/cpu_reliability.html
> А, ну это совсем другое дело (нет).
Ты у мамы дурачок? Нахуя мне пересобирать весь установленный софт, если обновилась только небольшая его часть?
> Беспруфный вскукарек от жирного финнского тролля
Ну да, ты ещё сходи в /b/ пасты в тнн-тредах пособирай, вот там уж точно образец научной мысли.
Жирный финский тролль написал ядро системы, на которой ты сейчас сидишь. Так что в области информатики он поумнее нас с тобой будет.
Ты что, зачем на двач заходишь, у тебя же с него ПРОЦЕССОР ИЗНОСИТСЯ.
В большинстве случаев сравним по скорости с джавой. Ну это ещё от того как писать и оптимизировать зависит.
Никак. Haskell это маня-язык, полностью состоящий из высокоуровневых математических абстракций. А для скорости нужны низкоуровневые операции.
>На самом деле Haskell это обычная Java, просто с другим синтаксисом.
На самом деле у тебя IT образование уровня /b/. Хаскель не Java, никогда не был и не будет Джавой, и вообще не имеет отношения к Джаве. Хаскель быстрее Джавы, а это значит, что он топ по производительности. Потому что быстрее Джавы только C# и компилируемые языки C/C++, Rust.
https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/haskell.html
Готов поставить два литра воздуха на то, что это можно как-то ускорить. В конце-концов, все эти абстракции в итоге разворачиваются в тот же асмокод
>все эти абстракции в итоге разворачиваются в тот же асмокод
Тот анон абсолютно безграмотен. Бесполезно использовать логику в споре с безграмотным человеком.
Он охуительно оптимизируется. Правда, чтобы наверняка хуярить оптимально, надо маленько разбираться, как он компилируется, плюс местами код изуродовать. Сама компиляция примерно такая, haskell -> core -> stg -> c-- -> (llvm/c/ncg) -> asm
Если не даун, то сможешь писать код, который выглядит просто и работает субоптимально (по сравнению с сишечкой).
GHC современный умный компилятор. Хаскель самый продвинутый язык по фичам, в него добавляют самые современные концепции. Советую почитать книгу Параллельное и конкурентное программирование на языке Haskell. Автор книги один из разработчиков Хаскеля и он немного рассказывает о том как разрабатывают Хаскель.
https://www.haskell.org/ghc/
К слову, ленивость позволяет в разы упростить код. С ней трудно совладать и понимать, где она нужна, а где нет, но когда всё понял, код такой получается, что прямо в кайф.
мимо
Ленивость позволяет создавать циклические и бесконечные последовательности. Ленивость позволяет избегать лишних вычислений. Хаскель может вычислять и лениво и энергично.
>Да и к тому же во время исполнения все это в любом случае транслируется в императивный ассемблер для аппаратной платформы.
И что? Аргумент уровня /b/. Всё равно что есть муку и фарш, запивая водой, вместо жареных чебуреков или другой выпечки с фаршем, аргументируя тем, что всё равно состав одинаковый и в желудке всё переварится в единое. Очень глупый аргумент.
лол, эта ерунда даже на низком уровне используется.
Я джун, вообще говоря
Если бы я мог резко соскочить со своей работы, то я бы пошёл. Работаю за те же деньги и не прогреом.
Где и остальные языки с гц. Веб сервисы, компиляторы, там где нужна относительно строгая система типов (про авиацию кто-то писал, хотя хз ибо там гц наверн табу) ...игры (в теории) например. Мне сложно придумать еще примеры т.к. я не знаю что в принципе делают на тех же жабах кроме как веб сервисы
Реальный прод? Не так чтобы нигде, вон на HN был недавно пост с serokell (https://serokell.io/blog/top-software-written-in-haskell) с примерами, в коммах накидали что это далеко не все (хотя на К. компания дропает хаскель (и ерланг, кложу и еще что-то) из-за того что на js/java проще людей найти, найс пример конечно).
Идеально можно на пруверы пойти еще, их можно использовать для каких-нибудь штук где важна безопастность. Но, конечно, никому не нужен стек на который никого не найти...
> Веб сервисы
Разве они не на PHP пишутся?
> компиляторы
Разве они не на Си пишутся?
> игры (в теории)
Сомнительно. Там же всё на OpenGL связано и движках, то есть только C++ и C#.
> Реальный прод?
Тут только Java.
> Идеально можно на пруверы пойти еще,
Имеется ввиду системы доказательства теорем? Мне кажется, за пределами двух-трёх НИИ это нигде больше не используется.
> их можно использовать для каких-нибудь штук где важна безопастность
Не совсем понял, о чём это. На любом современном языке можно писать безопасный код.
>Разве они не на PHP пишутся?
Где-то наверн, не только же, их же куча>>350401
>Разве они не на Си пишутся?
всм? зачем? разве что, чтобы портировать всюду, но зачем портировать какой нибудь perl6 на всякие эзотерические платформы. Хаскель особенно хвалят как инструмент для написания компиляторов из-за фич типо gadt'ов
>Сомнительно. Там же всё на OpenGL связано и движках, то есть только C++ и C#.
Да, сомнительно ибо нет тулзов почти. Но это хайлевельных. Биндинги для OpenGL, Vulcan, SFML, SDL2 есть. ECS есть. Для 2д простых игр хватит, да и написать движок можно. Шарп для игор ни чем не примечателен, разве что тулзами. Насколько на фп удобно игру писать....
>Тут только Java.
Дык я там скинул статью, примеры хаскеля в р.проде. И что значит - только Java - веб сервисы тоже прод, ты сам написал что там и PHP.
>Имеется ввиду системы доказательства теорем? Мне кажется, за пределами двух-трёх НИИ это нигде больше не используется.
Иногда появляются вакансии, на блокчейны например. Там люди свои для этого инструменты пишут, хз насколько они близки к пруверам но в требованиях пруверы указывают. Но да, от РБ это совсем далеко наверное.
>>350401
>Не совсем понял, о чём это. На любом современном языке можно писать безопасный код.
Но насколько просто? В Асм, Си, С++ писать безопасный код супер сложно из-за прямого использования памяти, UB и т.п. Не современные? В JS тоже сложно, т.к. минимум статических проверок. В расте (safe - borrow checker итп), шарпе (гц) попроще. Но проще - не значит, что нельзя еще проще. В пруверах ты буквально доказываешь корректность функций, на практике многое слишком трудоёмко доказывать - да, но во всяком случае многие классы ошибок можно избежать. В safe агде исключений тупо нет, как и вечных циклов.
ПВТ -> отсрочка, это единственный шанс на выживание
Что это значит?
А, действительно...
Как ни странно, та хаскелевакансия как раз на блокчейн. И я сейчас упорно пытаюсь подготовиться к собесу, потому что он будет с какими-то иностранцами
> Да и к тому же во время исполнения все это в любом случае транслируется в императивный ассемблер для аппаратной платформы
эталонный детектор васи из 8б
Какая у тебя реализация Фибоначчи, раз ты на нем потребление памяти смотришь?
Что если [a] мы будем сначала трансформировать в что-то типа [Maybe a], для которого определим (>>=) как-то так:
(>>=) :: [Maybe a] -> (Maybe a -> [Maybe b]) -> [Maybe b]
[] >>= f = f None
[x] >>= f = f x
(x:xs) >>= f = (f x) ++ (xs >>= f)
Меня не очень интересует как подобное запилить для нативного list comprehension. Мне интересно исключительно как называется подобная хуйня и формализовал ли кто-нибудь алгебру на ее основе.
ээ чепушила по русски можна ептыбля
По типам лажа полная выходит.
К тому же `m` в типе `>>=` не получится специализировать, чтобы получить `[Maybe a] -> (Maybe a -> [Maybe b]) -> [Maybe b]`
Максимум: `[Maybe a] -> (a -> [Maybe b]) -> [Maybe b]`
Даже если допустить такой тип для `>>=`, то непонятно, каков будет тип `return`, чтобы монадические законы соблюдались.
Да, ты прав, по типам полная хуйня, если оставаться привязанным к стандартным тайпклассам.
Есть функция, которая должна принять имя файла и при соответствии условию вернуть его тело минус заголовок
Сейчас оно жалуется на то, что у меня входящий тип IO String, и хочет просто строку. Но когда ставлю просто строку, оно хочет IO String. Тип возвращаемого значения вроде как в порядке
Я так понимаю, это особенности чисто функционального программирования? Как фиксить-то?
Как я уже писал, если я пытаюсь скормить ему просто строку, он начинает хотеть IO String
Возвращаемое значение в ио оберни,
readFile возвращает значение в ио.
<- просто сахар для >>=, почитай про монады и do.
Чтобы значение в монаду пихнуть юзай pure :: a -> m a
pure :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
если e :: m a, f :: a -> m b, m - Monad
do
x <- e
f x
эквивалентно
e >>= \x ->
f x
и имеет тип
m b
Начинающему — это буквально пара задач на кодварсе. Но я решил не мелочиться, и сразу пойти в реальные задачи
Я довольно слабо понял написанное, на самом деле. Ты описываешь pure как фвп, которая применяет монаду к аргументу, >>= как что-то пока малопонятное, а дальше совсем потерялся
Запись вида f :: a -> a понимаешь?
Это значит что функция f может работать с любым типом а.
Есть расширение чтобы писать явно
f :: forall a. a -> a. "для любого а, ф берет а и возвращает а".
pure :: Monad m => a -> m a, здесь m это любой конструктор типа (что-то, что берет тип и возвращает тип (тип типов , a :: , m :: -> ), тип это или конструктор типа -- выводится из контекста)
Monad m => это ограничение, говорит что использовать функцию pure можно только с такими m , которые реализуют интерфейс monad.
pure, как видно по типу, берет значение некого типа А и возвращает значение преобразованного типа M A.
считай просто оборачивает значение внутрь какой-то структуры M.
>>= это оператор с 2мя аргументами, первый - значение преобразованного монадой типа (m a), второй - функция, которая берет значение НЕпреобоазованного типа (а) и возвращает преобразованного (той же монадой) (но опционально другого) типа .
Можно представить что "m a" это вычисление значения типа "а" в каком-то контекстe "m"
тогда "x >>= f" позволяет выполнить операцию над значением в "х" не покидая контекст ("f" тут функция берущая "a", но "х" имеет тип "m a").
пример,
putStrLn :: String >>= IO ()
getLine :: IO String
"getLine >>= putStrLn" (или с лямбдой "getLine>>= \ x -> putStrLn x")
здесь m ~ IO, A ~ String, B ~ ().
у нас было значение строка внутри контекста консоль, мы сделали новое значение (типа (), unit) тоже в контексте консоли, но теперь наше значение несёт в себе ещё операции ввода строки и затем выводаее на консоль.
pure "str" :: IO String
значение строка в контексте консоли, без каких-либо эффектов
у тебя есть свой код, оперирующий строками
пусть он будет в функции f :: String -> String
ты хочешь функцию, которая принимает строку (имя файла), применяет операцию f к прочитанному содержимому файла и возвращает его
какой тип функции?
openFile берет строку, значит "String ->"
возвращает тоже строку, значит в конце "String"
внутри ты читаешь из файла - это возможно только внутри контекста консоли, т.е. монады IO, значит возвращаемая строка будет типа "IO String"
openFile :: String -> IO String
openFile file = ?
замечу, readFile :: String -> IO String,
значит readFile file :: IO String
нужно ещё применить f к прочитаному, т.е. возвращать операцию которая будет сначала читать, а потом поменять f
readFile file >>= f нельзя, так как f возвращает просто строку, а >>= требует чтобы ф возвращало строку в том же контексте, в котором находился первый аргумент
readFile file >>= \ x -> ?
x имеет тип String, f x :: String
нужно это обернуть в контекст, значит используем pure
readFile file >>= \ x -> pure (f x)
это ты мог записать с помощью сахара do так:
do
x <- readFile file
pure (f x)
прим.
если нужно применить операцию над значением внутри контекста, но операция сама по себе контекста не требует, можно юзать fmap или (<$>)
fmap :: (a -> b) -> m a -> m b
с ним тело функции openFile можно записать как
fmap f (readFile file)
или
f <$> readFile file
Запись вида f :: a -> a понимаешь?
Это значит что функция f может работать с любым типом а.
Есть расширение чтобы писать явно
f :: forall a. a -> a. "для любого а, ф берет а и возвращает а".
pure :: Monad m => a -> m a, здесь m это любой конструктор типа (что-то, что берет тип и возвращает тип (тип типов , a :: , m :: -> ), тип это или конструктор типа -- выводится из контекста)
Monad m => это ограничение, говорит что использовать функцию pure можно только с такими m , которые реализуют интерфейс monad.
pure, как видно по типу, берет значение некого типа А и возвращает значение преобразованного типа M A.
считай просто оборачивает значение внутрь какой-то структуры M.
>>= это оператор с 2мя аргументами, первый - значение преобразованного монадой типа (m a), второй - функция, которая берет значение НЕпреобоазованного типа (а) и возвращает преобразованного (той же монадой) (но опционально другого) типа .
Можно представить что "m a" это вычисление значения типа "а" в каком-то контекстe "m"
тогда "x >>= f" позволяет выполнить операцию над значением в "х" не покидая контекст ("f" тут функция берущая "a", но "х" имеет тип "m a").
пример,
putStrLn :: String >>= IO ()
getLine :: IO String
"getLine >>= putStrLn" (или с лямбдой "getLine>>= \ x -> putStrLn x")
здесь m ~ IO, A ~ String, B ~ ().
у нас было значение строка внутри контекста консоль, мы сделали новое значение (типа (), unit) тоже в контексте консоли, но теперь наше значение несёт в себе ещё операции ввода строки и затем выводаее на консоль.
pure "str" :: IO String
значение строка в контексте консоли, без каких-либо эффектов
у тебя есть свой код, оперирующий строками
пусть он будет в функции f :: String -> String
ты хочешь функцию, которая принимает строку (имя файла), применяет операцию f к прочитанному содержимому файла и возвращает его
какой тип функции?
openFile берет строку, значит "String ->"
возвращает тоже строку, значит в конце "String"
внутри ты читаешь из файла - это возможно только внутри контекста консоли, т.е. монады IO, значит возвращаемая строка будет типа "IO String"
openFile :: String -> IO String
openFile file = ?
замечу, readFile :: String -> IO String,
значит readFile file :: IO String
нужно ещё применить f к прочитаному, т.е. возвращать операцию которая будет сначала читать, а потом поменять f
readFile file >>= f нельзя, так как f возвращает просто строку, а >>= требует чтобы ф возвращало строку в том же контексте, в котором находился первый аргумент
readFile file >>= \ x -> ?
x имеет тип String, f x :: String
нужно это обернуть в контекст, значит используем pure
readFile file >>= \ x -> pure (f x)
это ты мог записать с помощью сахара do так:
do
x <- readFile file
pure (f x)
прим.
если нужно применить операцию над значением внутри контекста, но операция сама по себе контекста не требует, можно юзать fmap или (<$>)
fmap :: (a -> b) -> m a -> m b
с ним тело функции openFile можно записать как
fmap f (readFile file)
или
f <$> readFile file
Пока что я сошёлся с собой во мнении, что лезть в монады буду по мере необходимости. Пришлось часть функционала запихнуть в мейн, но прочитать заголовок я смог. Осталась проблема конвертации byteString в Int. В hoogle ничего похожего, да и в функциях из byteString тоже. Как?
В байтстринге что-то вида текста "12"? Можно в стринг преобразовать сначала.
"read . BS.unpack"
если нужно побайтово смотреть то я хз, погугли binary мб
В байтстринге сырые байты, часть из которых тест и прекрасно интерпретируются, а часть — инты, которые я не могу вытащить
Что мертво, умереть не может.
Там, где можно, Optional/Maybe вообще лучше избегать. Если функция возвращает строку, возвращай в случае фейла пустую, если список, возвращай пустой список, если инт, то -1 (если негативные значения не используются). Мейби бейби это нечитабельная дрисня.
удачи не проеьаться забыв проверять невалидные / ошибочные значения, лучше уж исключение кидать, если больно обработку кажд раз писать
Это варик не для параноиков, не спорю.
Хотя у Мейбилэнд есть хорошее свойство, что если что-то одно выкинет Nothing, то весь результат будет Nothing, почти как исключение.
Кидать исключения тоже не для параноиков, но и не даёт молча юзать невалидный ответ.
Даня Крюгер считает, что дорос критиковать ФП, выбрасывая бессвязный текст в тред.
>решил попробовать хаскель
>скачал 40мб инсталлер
>тот насрал в корень диска и отказался работать
>пошел качать в ручную ghc
>тот весит больше чем jdk
это точно продукт не от микрософта?
Вы будете смеяться, но процесс установки Хачкеля на рач пинус точнее на бомжару меня заставил усомниться, что ФП для умных людей. Стак нормально поставился, но когда я попытался установить расширение на вскод, оказалось, что ему нужен GHCup, что вообще отдельная хуйня, но там внутри свой стак и компилятор. Когда я и его поставил, вскод долго не мог найти его путь, лишь чудом его нашел. Еще он юзал bash вместо моего zsh и с этим тоже были какие то проблемы, и не подтягивал системное прокси (на работе я могу сидеть только через него, иначе без доступа к интернету).
Но вишенкой на торте стало, что при каждой открытой вкладке с кодом на Хаскеле это ебаное расширение проверяет обновления, то ли себя, то ли GHCup, и если у него это не получилось, он отказывается работать. Естественно, прокси он тоже не подтягивал.
Во-первых, по моему это блядь лакмусовая бумажка, что для самого популярного 2к22 редактора расширение для Хаскелля высранное дегенератами ебаное говно. Конечно, все коммьюнити не отвечает на нескольких человек, но блядь, каковы были шансы?
Во-вторых, нахуй тулсет Хачкеля такое запутанное месиво? Видно сразу почерк любителей писать нечитаемые однострочники вместо понятного кода.
Прокси и кастомными шелами не пользуюсь - нечего сказать. А так, ghcup прекрасно ставился и работал и на нескольких линухах и на винде (на винде мб платформа ещё была правда), расширение на вскод тоже сразу работает. Правда только со своим, мелким, проектом (однофайлы не видит, большой проект с инета игнорил), но проблем со связкой установленных ghc/cabal'a не было.
>ему нужен GHCup, что вообще отдельная хуйня, но там внутри свой стак и компилятор
В расширении можно настроить на использование path, вместо автоматич установки/юзания ghcup.
>нечитаемые однострочники
Если ты про названия, то сравни с далёким от хс Си - ещё хуже. Если про попытки вписать функцию в строку - то это не связано с ФП, и, так-то, вездесуще.
Потому что эта хуйня сделанная математиками с математическим сленгом, который хуй проссышь. Научить рандомного человека писать на жабе проще.
то есть это так и было задумано?
просто я хотел погрузиться в мир фп
но пока что лишь вступил в говно
если язык позволяет себе обсираться уже в таких моментах
то чего мне от него ждать дальше
потому что он сложный пиздец
>более безопасные и логически завершённые программы
нахуй никому не нужны, когда можно хуяк-хуяк и в продакшн.
Там где нужна безопасность часто не принимается жирный рантайм/ленивость/GC. А в остальных случаях конкуренцию составляют другие ФП яп аля скалы на жвм, агды с пруфами итп.
персонаж аниме
Моноиды в категории эндофункторов.
Инстанс
class Monad m where
(>>=) :: m a -> ( a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
Такой что
return a >>= k = k a
m >>= return = m
m >>= (\x -> k x >>= h) = (m >>= k) >>= h
Можно ли на хаскеле заниматься NLP и машинным обучением?
Можно поподробнее?
Я вообще случайно твой пост увидел и в тред зашел, поделюсь необоснованным мнением.
У меня есть подозрения, что код на любом языке можно записать в процедурном виде на си, а там уж скомпилировать. Эта вся лямбда хуйня тупо абстракция же. Вангую, на машинном уровне те же процедурки и стеки.
Ну например самые простые кейсы:
1) сколько байт занимает в хаскеле значение типа "число";
2) как будет представлен в памяти тип данных "массив";
3) предыдущий вопрос, только для типа данных "структура" (таких правда в хаскеле нет, есть дата тайпы, но в принципе это же "структура", ведь так?);
4) если хаскеловская функция вернёт функцию замкнутую на свои аргументы, какие структуры будут при этом лежать в памяти (тут имеются ввиду байтики)?
Я вообще за хаскель не шарю, пять лет назад в этот тред заходил ради интереса. Ну вот давай подумаем логически, к примеру
>2) как будет представлен в памяти тип данных "массив"
Допустим, ты знаком с алгоритмами/контейнерами, как бы ты на C/C++ реализовал ленивые вычисления? Ну самый прямой способ, создать динамический массив типа std::vector и пополнять его по мере необходимости, или же unordered_map, чтобы кэшировать значения функции для части аргументов.
1 Int - самый распространенный наверное - слово, но пару бит на тег, есть неограниченные из gmp, есть и 8/16/32/64 бит (и boxed и нет)
2 массивы есть как массивы, но не в стдлибе, в ней основная структура - связный список
3 data по умолчанию хранит thunk'и - ленивые значения, но может и не ленивые; по умолчанию все boxed, есть распакованные типы, но сомневаюсь, что можно несколько таких объединять в полностью распакованную структуру, распакованные кортежи например неюзабельны из-за налагаемых ограничений
А хули ты хотел 3,5 борщехлеба лениво дергают свои монады это тебе не js обезьянник
У (<*>) ассоциативность левая, у (:) правая.
На нем пишут же даже
- стандартный менеджер кабал постоянно проебывается с зависимостями, начинаешь откатывать ghc - одно лечится, другое отваливается. А я хочу его использовать по нижеупомянутой причине. Пиздец какой-то
- стак благодаря контейнеризации кое-как их разруливает, но кидать глобальные пакеты в юзерский профиль? Серьезно? А пуллреквест с патчем этого непотребства до сих пор висит открытых, причем автор сдался его поддерживать лул
- Расширений для иде 2,5 штуки, причем одно не поддерживается уже больше года, второму надо снижать версию ghc и для оставшегося надо руками доустанавливать одноименный пакет чтобы отладка работала
- Исходя из пункта выше, актуальных идешек всего две, вим и вскот, само собой как нормис я оба считаю неюзабельным говном, к саблиму как раз тухлый плагин идет
- Отсутствие нормального версионирования дабы разрабы могли свои пакеты подбивать к той или иной лтске
- Как следствие, депхелл ебанутый просто. Еще и распространение в виде исходников, сборка которых висит на одном потоке проца по десять минут, заебись. Как там владельцы ноутов поживают я даже представлять не хочу
Пойду с лицом лягушки кидать симлинк на профиль стака, но это всё булшит полнейший. Вся красота языка зарублена хуевейшей поддержкой, чем-то напоминает ранний раст, который еще какой-то отчаянный на микроконтроллеры натягивал.
foo bar = yoba bar where yoba = ...
Это нормально, что у меня от такого лицо скрючивается?
Можно ведь по-человечески:
foo bar = let yoba = ... in yoba bar
Или я просто не просветлился в должной степени и из меня лезут мерзкие процедурно-императивные привычки?
>актуальных идешек всего две, вим и вскот
Есть редактор helix (https://github.com/helix-editor/helix) само сабой, написан на расте, это такой вим, который не надо настраивать два месяца. Поддерживает лэнгвидж серверы в принципе и хасельный в частности.
Это кстати вроде относительно недавно (может быть пару лет) стало модно. Сам where синтаксис конечно давно был, но вот разбивать на кучу подвыражений, вские там "= go where", лесенки из нескольких уровней вложенных where - все это относительно недавно стали лепить кмк. Хотя на мой взгляд вроде неплохо.
Нужно осознать что ФП вертит в рантайме синтаксическое дерево, а не выполняет раз-два-три. Вдохновись сначала лиспом/схемой, он проще и понятнее.
Класс типов с определёнными свойствами. Можешь считать что они реализуют некоторый интерфейс.
Просто я привык читать код сверху вниз, а с where приходится наоборот. Наверное удобно, когда имена хорошо подобраны, но это не всегда так.
Еще глаз цепляется, когда паттерн матчинг выносят в сигнатуру функции, такое еще в эликсире встречал. Если у тебя один case ... of, то прошелся взглядом по строкам, сопоставил паттерн и возвращаемое значение и доволен, а с сигнатурами приходится парсить строки в голове.
Удвою.
Пока пытался понять смысл композиции (.), меня осенило, что функции в хаскеле похожи не на последовательность инструкций, а на конвейер, где входные данные пересобираются в выходные. После этого стало гораздо проще изучать язык.
Мимо почти год балуюсь литкодом и читаю книжку Хаттона
А мне нравится, это математично.
С переменными перед выражением возможна была однопроходная компиляция, но к хаскелю это в принципе неприменимо.
HLS в любом редакторе, поддерживающем LSP работает. На работе половина чуваков в vscode сидит
Емакс
У этого говна IDE существует вообще? Под мобилку прогу сделать например
640x368, 0:31
RAD IDE програмить мышкой, копипаст кода из чатГПТ
Мне после изучения хаскеля показалось, что все программирование это про преобразование одних данных в другие.
Это сложно назвать разморозкой - у меня практически первый язык.
Перед изучением хаскеля есть смысл навернуть SICP.
Это вообще пожалуй единственный случай когда есть смысл читать SICP лол.
Cool story bro
Есть, но она одна
Джавамуха уже и в хаскель-тред протекла, спешите видеть
Типы во время компиляции стираются. Если нужно паттерн-матчить по типу, то придется таскать его с собой. Смотри dynamic \ type families \ singletons
А зачем тебе такое? Может твоя проблема решается как-то по другому? Если нет, то анон выше правильно сказал про dynamic/typeable, но это вообще не хаскель-вей.
Правда кейс сделать не получится - нужно будет кастить к каждому типу и смотреть скастилось или нет.
Да
Криптоштуки и немного бэка.
Почему тип результата в сигнатуре функции пишется в цепочке аргументов? Разве не логичнее было бы писать отдельно, вроде
f :: a -> b :: c
или
f :: c :: a -> b
вместо
f :: a -> b -> c
?
Каррирование
Потому что то, что ты написал парсер в мозгу хаскелиста распарсит как "функция f из a в b является типом c".
У всех хачкелистов проблемы с построением предложений?
Ооо, ты вспомнил.
Вот как бы я не любил ООП, ФП это просто горящий мусорный бак вещей, которые не представляют никакой ценности, кроме выебонов, а на практике даже вредны.
В хаскелле я могу не писать аргументы функций, а определять их как композицию функций. Хорошо, могу. Кто-нибудь мне объяснит, нахуя? Нет, это не делает код читаемым, это делает его нечитаемым, потому что вместо того, чтобы посмотреть, какие у функции аргументы, мне придется перейти к определению минимум еще одной функции, если конечно она тоже не пойнт фри.
Да и вообще деление кода на кучу мелких функций это рак ебаный, потому что приходится прыгать по файлу, а то и по файлам при чтении кода, когда можно было бы просто прочитать код в линейной манере, будь он нормально написан. Обфускация кода встроенная на уровне парадигмы. А в Хаскелле это еще и обмазано ленивостью, поэтому удачи в отладке всего этого месива. Тьфу, блядь.
> В хаскелле я могу не писать аргументы функций, а определять их как композицию функций. Хорошо, могу. Кто-нибудь мне объяснит, нахуя?
Это не "нахуя", а просто следствие того чем являются и как определяются функции в хаскеле. Не нравится\не понимаешь\не умеешь такой стиль - запрети линтером, не пропускай такое на код ревью и радуйся своим понятным аргументам a и b. Размер функций язык вообще никак не форсит, так что совет тот же.
Ленивость да, иногда срет в кашу и нужно понимать.
>не пропускай такое на код ревью
А если я не помидор? А если я читаю чей то гитхаб и там такая параша? Проблема то не в том, что на ЯП нельзя в принципе делать иначе, проблема в том, что ЯП позволяет так делать, а в его коммьюнити так делать модно.
В таком случае делаешь всё тоже самое, что и с другими языками - читаешь и не бухтишь.
Не знаю, честно говоря, чем тебе композиция не угодила. Твои аргументы хуйня, но мне лень оппонировать, да и смысла в данном случае нет.
Штука в том, что если в языке что-то можно сделать более чем одним образом - всегда будет кто-то недоволен тем, что кто-то другой выбрал другой способ. Разве что выпиливать вообще возможность это делать, но тогда получится go и будут бухтеть что это сделать вообще нельзя.
Тебе просто не повезло не любить, когда используют композицию, поэтому для тебя всё фп это горящий мусорный бак теперь.
>мне лень оппонировать
Поэтому ты уже два сообщения высрал?
>Тебе просто не повезло не любить
Да уж не свезло, не смогу теперь похлебать борщей, придется зарабатывать.
>поэтому для тебя всё фп это горящий мусорный бак теперь.
Для меня горящий мусорный бак -- это конкретно идиоматическое ФП. На бумаге оно кросивое, но на практике погромистам приходится мириться с фактом, что компьютеры -- это машины Тьюринга, а не лямбда вычислители. А пойнт фри функции -- это только часть общей картины.
Против элементов ФП в других языках я ничего против не имею. Да и против Хачкелля так то тоже, если бы с ним не носились по всему интернету как со змеиным маслом, а просто себе тихо решали 3.5 специализированные задачи в финтехе (или где он там есть) и строчили паперы в НИИ.
> Поэтому ты уже два сообщения высрал?
Ага. Два высера, написанные левой ногой. Ну хоть какой-то движ в мертвом трее.
> Да уж не свезло, не смогу теперь похлебать борщей, придется зарабатывать.
Уже неплохо. Кто-то вон вообще на жаваскрипте зарабатывает.
> Для меня горящий мусорный бак -- это конкретно идиоматическое ФП.
Ну, хуево быть тобой, наверное.
> Против элементов ФП в других языках я ничего против не имею.
Хех, а мне вот вечно хочется композиции нормальной или алгебраических эффектов - а хуй. Или синтаксис сопротивляется изо всех сил или система типов жидко в портки наваливает. В обоих случаях настолько хуево получается, что лучше и не пытаться. Всё фп в итоге начинается и заканчивается на map-filter-reduce.
>Да и против Хачкелля так то тоже, если бы с ним не носились по всему интернету как со змеиным маслом, а просто себе тихо решали 3.5 специализированные задачи в финтехе (или где он там есть) и строчили паперы в НИИ.
И всякие конпеляторы с дслами и кодогенераторами ещё, и перекладывание жсонов и даже хардварь особо ебанутые делают. Папиры в последнее время больше на агде как-то.
А где во всём интернете носятся, кстати? Я как-то не замечал особо. Везде дефолтные жаба\питон\жс и периодически растоебы в очередной раз что-то переписали\предлагают переписать. Гошники раньше тоже бегали, но куда-то все делись
>Вот как бы я не любил ООП, ФП это просто горящий мусорный бак вещей
>Да и вообще деление кода на кучу мелких функций это рак ебаный
>Не знает про букву S в SOLID за который все топят
>Кто-нибудь мне объяснит, нахуя?
Чтобы не придумвывать названия переменным.
>Нет, это не делает код читаемым, это делает его нечитаемым
Все хорошо в меру, никто не заходит специально на https://pointfree.io/
вбивая туда весь свой код. Как правило если функции не унарные, то пойнтфри уже не будет использоваться потому что код действительно превращается в нечитаемую парашу.
>Да и вообще деление кода на кучу мелких функций это рак ебаный
Делю функции на части, которые собираюсь где-то переиспользовать например в тех же тестах. Не писать же мне это ещё раз. Деление на мелкие функции должно происходить так, чтобы по названию функции было понятно, что она делает, это никак не мешает читать код в линейной манере, если тебе конечно не нужны все детали кода разом. Вообще какая-то непонятная претензия - это точно такая же абстракция как во всех других языках.
Надо иметь отрицательный айсикью, что порваться от каррирования и композиций. Ты просто неосилятор. Смирись.
Не, я наоборот уроки по хаскелю прохожу ради изучения фп.
Я и с императивными языками стараюсь дробить функции, да еще и по разным файлам, чтобы избежать повторов кода и уменьшить количество аргументов: такие функции наоборот легче читать, тестировать и менять, чем ебучие простыни, благодаря точному имени, маленькой сигнатуре и чистоте, делающей результат зависящим только от скормленных аргументов. Одну большую функцию еще можно как-то читать, пока в ней нет ветвлений, но с ними получается каша, когда ты просто пролистываешь половину кода функции, смотришь в циклы, возвращаешься на 100 строк обратно и тд, с мелкими же функциями ты просто смотришь на дерево не вдаваясь в детали.
Кстати, с фп особо отлаживать не приходится: я не знаю как так происходит, но ты просто пишешь код и он работает но писать сложнее
Но к хаскелю, кроме как изучения фп, я не притронусь - в рот его ебал.
>>768802 хуй
>я не знаю как так происходит, но ты просто пишешь код и он работает
За это как раз таки отвечает ебанутая система типов. Большинство видов некорректного кода отсеивается на этапе компиляции. Не представляю сейчас как люди в других языках обходятся без этого.
>но писать сложнее
Придёт с опытом.
>>778323
https://hackage.haskell.org/package/tuple-0.3.0.2/docs/Data-Tuple-Curry.html#t:Curry
Чем отличается обращение к глобальной "переменной" внутри функции от передачи контейнера, где лежит эта переменная и еще n ей подобных, в качестве аргумента этой функции?
Результат зависит от значения контейнера, так что вроде referential transparency есть, но в то же время извне не видно, к какой части контейнера функция будет обращаться.
c = 11
d = 2
f1(a, b) {
return d (a + b - c)
}
x = f1(1, 11) ; 2
Против
s = { c = 11, d = 2 }
f2(a, b, g) {
return g.d (a + b - g.c)
}
x = f2(1, 11, s) ; 2
И что, собственно, тебя волнует? Ссылочная прозрачность? Ну так это следствие чистоты функций. Оттуда и следует ленивость. Компилятор чистого языка всё видит. В хаскелле, например, оба примера будут исполнятся одинаково лениво, если только ты не укажешь строгость членов в объявлении структа.
То, что функциональщиками подается использование глобальных переменных как что-то плохое, в то время как эти же переменные можно использовать просто поместив в один контейнер и передав в качестве аргумента. Есть прозрачность на контейнер, но не обращение к его содержимому. Компилятор при желании и обращение к глобальным переменным увидит.
В функциональных языках нету глобальных переменных. Ты не понимаешь что такое ссылочная прозрачность. У тебя в голове каша. Иди учи матчасть.
Я за этим и пришел.
В монаде списка
do
x <- [1..n]
y <- [x..n]
Это тоже самое, что [ ... | x <- [1..n], y <- [x..n]]. Т.е. перебор всех y в диапазоне [x..n] для каждого x в диапазоне [1..n]. Что-то типо вложенных циклов.
Далее return в монаде списка просто создаёт список из одного элемента. Т.е. для каждой указанной выше комбинации, ты создаёшь одноэлементный список и применяешь к нему функцию guarded, которая если условия не выполняется превращает список в пустой список. Ну и в конце все результаты просто конкатинируются.
А, ну да, concat
Есть же instance, там написано...
С хаскелем дня не проходит без такого момента ВТФ из гоин он
guard кстати библиотечная функция. Можно переписать на
x <- [1..n]
y <- [x..n]
guard $ x * y == n
return (x, y)
import Data.List.Split
readDouble = read :: (String -> Double)
parseMtx :: String -> [[Double]]
parseMtx s = map ((map readDouble) . words) $ endBy ";" s
можно ли сделать что-то по типу такого?:
readDouble :: Fractional a => String -> a
readDouble = read
parseMtx :: Fractional a => String -> [[a]]
parseMtx s = map ((map readDouble) . words) $ endBy ";" s
Да, только придется добавить read в констрейнты, потому что произвольный fractional не обязан иметь инстанса read, в отличии от дабла у которого компилятор спокойно находит этот инстанс.
Read*
Хотя проблема еще осталась.
У меня есть функции
s :: (Read a, Fractional a) -> String -> [[a]]
и
m :: MArray arr cs e => Image arr cs e -> [[Pixel cs e]] -> Image VU cs e,
которую я вызываю как m _ $ s _ (пиксел является Fractional)
и для Pixel Read я не понимаю как указать, а когда в s было просто Fractional, а вместо рида был свой парсер даблов все работало
Можешь показать код полностью или хотя бы прилепить выхлоп компилятора? Скорее всего опять не хватает каких-то констрейтов.
instance DisjunctionType A
instance DisjunctionType B
g :: DisjunctionType t => (A, B) -> t
g (a, _) = a
почему этот код не компилиться? сообщение какое то невнятное
Couldn't match expected type ‘t’ with actual type ‘A’
‘t’ is a rigid type variable bound by
the type signature for:
g :: forall t. DisjunctionType t => (A, B) -> t
У тебя сигнатура обещает, что функция полиморфная, а реализация на самом деле работает с конкретными типами. Поэтому типы не сходятся.
А ты используй Result<_,_>. Option только для проверки на пустое значение. И делай Result.bind и Result.map.
А причем тут собственно хаскель и фп?
Так же само можно спросить, чем отличается обращение из функции к глобальной переменной или к своему аргументу- некоему объекту через его публичный интерфейс. Дохуя чем.
Да, я прод пишу.
Это копия, сохраненная 13 февраля в 04:34.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.