Вы видите копию треда, сохраненную 12 ноября 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.
Medium - http://book.realworldhaskell.org/read | https://www.goodreads.com/book/show/25587599-haskell-programming
Concurrency - http://chimera.labs.oreilly.com/books/1230000000929/index.html
Web - http://www.yesodweb.com/book
ХеллоуУорлды в монады оборачивать здесь -> https://www.codewars.com
Перфоманс хаскеля трудно измерить в принцпие из-за встроенной ленивости, он может по скорости в догонять языки без GC, а может взять в рот и питухона.
В принципе это есть один из реальных недостатков хаскеля
https://github.com/jystic/hadoop-tools/tree/master/hadoop-tools
Ну вот неплохой пример. Хотя не знаю что там спаливать. Программа на хаскеле это цепочка функций, которая внезапно, обрабатывает данные.
Вот и весь секрет. Остальное собсно твой скилл кодинга, алгоритмов, умение создавать композиции, которые, в принципе - оторваны от парадигмы
С такими вопросами в ПХП/Java тред.
Спасибо, я знаю, я лиспер.
Просто по такому коду быстро въезжаешь в язык, удобно. Если взять сразу какой-нибудь pandoc, то неделю потратишь только на то, чтобы понять связи между частями проекта (образно говоря), вместо того, чтобы учиться на кусочках кода.
http://honza.ca/2012/10/haskell-strings
Ох и вбросил так вбросил
ну наверное на то что наивное решение на хаскеле пососало немытых хуйцов в производительности. Но чо поделаешь, язык не сильно под числодрочение и скриптование заточен.
Я правильно понимаю, что он в одной куче сравнивает скомпилированные программы на Го и Сях и интерпретируемые программы на хачкеле, питоне и ноде?
Версия с вшитым оглавлением. Теперь это можно читать — http://m.turbobit.net/tj2jrpany0vy.html
Уровень - введение в хачкель. По ходу изложения автор пилит некий проект. Либы, что в нем используются, уже не актуальны, поэтому практиковать по ходу изложения новичку проблематично. Эту книгу рекомендовали здесь в былые времена.
> Начинай с The Haskell School of Expression дальше читай Typeclassopedia (http://www.haskell.org/wikiupload/8/85/TMR-Issue13.pdf), дальше статьи по ссылкам в тайпклассопедии, викикнигу (http://en.wikibooks.org/wiki/Haskell), а точнее отдельные главы. Ну и вики на haskell.org.
> Некоторые няшечки могут посоветовать Душкина (беги от этой книги, как от чумы), Грема Хаттона или "Изучи себе хаскель во имя великой справедливости" - не слушай их, только напрасно потратишь время.
> Изучи себе хаскель во имя великой справедливости
Вот да, нудновато, многабукав, и волшебно уметь в хаскель не начинаешь.
Впервые вижу сколь-либо интересный аргумент за безтиповое программирование, хотя все равно звучит похоже на "нахуй нам ваши типы, мы в болоте посидим"
Мы дрочим на монады, а не на строки.
.+ .* .- ./
>-- | Safely doesn't perform IO with the help of acme-dont. Side-effects-free!
>safePerformIO :: IO a -> Maybe (IO ())
>safePerformIO = Just . don't
https://hackage.haskell.org/package/acme-safe-0.1.0.0/docs/src/Acme-Safe.html
10 из 10
Проиграл.
Почему-то больше проиграл с того, как safeTrace реализована через safePerformIO. Напомнило fizzBuzzEnterpriseEdition.
https://www.ohaskell.guide/
+ ищи русский перевод Learn you a haskell
Это тебе не джава, без английского далеко не уйдешь.
Зачем выкладывать книги на помойках, если есть либген? (Залил бы туда, но мне лень)
>>088712
Учебник от Anton K попробуй
https://anton-k.github.io/ru-haskell-book/book/home
А вот это как? Разбирался в хачкелле кто по этому материалу?
>на руззком
Ох лол, ты уверен что ты правильную сферу деятельности выбрал?
Не читаю на пидарашкенском since 2007
Я ни в чем не уверен в этой жизни.
Аппликативные функторы хорошо зделоны.
Есть ли фриланс на хаскеле?
Я вот тут от балды написал прикладной http сервант на ocaml, что бы несколько спустя дней сыпя проклятиями переметнуться на хаскелл, напиать от балды сервак на нем и успокоиться. Так что не все так однозначно, особенно учитывая то, что уже haskell 6.12 имеет конкурентный сборщик мусора и сам из коробки умеет использовать несколько ядер.
1) Откровенный, признанный в рассылке баг в Lwt, собранный с ним ocsigen, фикс есть, но надо почти весь окамловый мир пересобрать. Даже на ubuntu 10.10 он еще есть.
2) Если жить с этим багом, то это приводит к тому, что сервер становится блокирующим. Это вообще неприемлемо, при сколь угодно маленьких нагрузках
3) Собранный хаскеллем бинарник будет жить на любом вообще почти линуксе --- там динамические зависимости от малого количества системных библиотек. Его не поломать сменой энвайромента
4) На окамле так теоретически можно, на практике за половину дня у меня не получилось (может я тупой, но я лучше буду на хаскелле код писать, чем бодаться со сборкой и путями к библиотекам и чтением манов на ocamlfind)
5) Happstack очень хороший и он проще в использовании, чем Ocsigen, хотя и не такой пока навороченный. Но лучше все равно.
6) 90% из того, что я пишу в окамле руками, в хаскелле уже есть
7) В компиляторе хаскелла правильный подход к компиляции, к представлению значений в памяти, и люди над компилятором работают, а не занимаются черти-чем. Это значит, что момент, когда хаскелл станет уделывать окамл по вычислениям --- неизбежно наступит, это только вопрос времени. Представление чисел в Окамле --- это какой-то позор, при том, что есть SML/MLTon и Эндрю Аппель. Работа с этими числами и их типами при отсутствии тайпклассов --- это тоже позор. Так что окамл быстро работает только на 31-битной арифметике (ну или 63-битной, но я не уверен, что в 64-битной сборке примитивные типы 63-битные) Может, в хаскелле оно вообще сейчас боксед всё, я не знаю, но динамика развития компилятора говорит о том, что это временно
8) Темпы развития компилятора и рантайма хаскелла - в нём уже есть конкурентный сборщик и масштабирование по ядрам, а не отмазки, что это все сложно и потребует больших переделок. Работает само (на примере хаппстека). Т.е. теже драйвера HDBC --- уже сами по себе написаны в неблокирующей манере и прозрачно работают с ForkIO, а не требуют запуска в нативных тредах или переписывания, как окамле (я не говорю про качество самих драйверов еще).
Я вот тут от балды написал прикладной http сервант на ocaml, что бы несколько спустя дней сыпя проклятиями переметнуться на хаскелл, напиать от балды сервак на нем и успокоиться. Так что не все так однозначно, особенно учитывая то, что уже haskell 6.12 имеет конкурентный сборщик мусора и сам из коробки умеет использовать несколько ядер.
1) Откровенный, признанный в рассылке баг в Lwt, собранный с ним ocsigen, фикс есть, но надо почти весь окамловый мир пересобрать. Даже на ubuntu 10.10 он еще есть.
2) Если жить с этим багом, то это приводит к тому, что сервер становится блокирующим. Это вообще неприемлемо, при сколь угодно маленьких нагрузках
3) Собранный хаскеллем бинарник будет жить на любом вообще почти линуксе --- там динамические зависимости от малого количества системных библиотек. Его не поломать сменой энвайромента
4) На окамле так теоретически можно, на практике за половину дня у меня не получилось (может я тупой, но я лучше буду на хаскелле код писать, чем бодаться со сборкой и путями к библиотекам и чтением манов на ocamlfind)
5) Happstack очень хороший и он проще в использовании, чем Ocsigen, хотя и не такой пока навороченный. Но лучше все равно.
6) 90% из того, что я пишу в окамле руками, в хаскелле уже есть
7) В компиляторе хаскелла правильный подход к компиляции, к представлению значений в памяти, и люди над компилятором работают, а не занимаются черти-чем. Это значит, что момент, когда хаскелл станет уделывать окамл по вычислениям --- неизбежно наступит, это только вопрос времени. Представление чисел в Окамле --- это какой-то позор, при том, что есть SML/MLTon и Эндрю Аппель. Работа с этими числами и их типами при отсутствии тайпклассов --- это тоже позор. Так что окамл быстро работает только на 31-битной арифметике (ну или 63-битной, но я не уверен, что в 64-битной сборке примитивные типы 63-битные) Может, в хаскелле оно вообще сейчас боксед всё, я не знаю, но динамика развития компилятора говорит о том, что это временно
8) Темпы развития компилятора и рантайма хаскелла - в нём уже есть конкурентный сборщик и масштабирование по ядрам, а не отмазки, что это все сложно и потребует больших переделок. Работает само (на примере хаппстека). Т.е. теже драйвера HDBC --- уже сами по себе написаны в неблокирующей манере и прозрачно работают с ForkIO, а не требуют запуска в нативных тредах или переписывания, как окамле (я не говорю про качество самих драйверов еще).
>6) 90% из того, что я пишу в окамле руками, в хаскелле уже есть
А ты какой стдлиб используешь, братишка?
Алсо, тайпклассы - зло.
это паста 2010 года?
А кому нереально?
Нужны ADT? Их нет, но 'type Vehicle = {type:"CAR", ... }|{type:"TRAIN", ...}' в сочетании с 'let handlers = {CAR: handleCar, TRAIN: handleTrain}' даст подобие паттерн-матчинга с exhaustiveness check.
Нужны тайпклассы? Их нет, но вместо 'sort :: Ord a => [a] -> [a]' можно определить 'sort<A>(ctx: { compare: (A, A) => "EQ" | "GT" | "EQ" }, a: A[]): A[]', что уступает в изяществе и удобстве, но работает не хуже.
Нужна чистота? Можно завернуть все в Eff с какими пожелаешь эффектами.
Нужна do-нотация? Так не нужна же.
Нужно содомизировать свой код, игнорируя корректность происходящего в некоторых его частях? Тайпчекер не станет мешать, babel выкинет типы без каких-либо возражений, не заставляя исправлять каждый недочет.
Выходит, что в JS доступна значительная часть плюсов продвинутых систем типов, но при этом не приходится преодолевать их ограничения. Зачем же использовать что-либо более строгое?
>Зачем же использовать что-либо более строгое?
Затем, что есть clojurescript.
мимокапитандекомплектед
Рич, отъебись. Пока не объяснишь внятно, как рефакторить тысячи строк кода без единого теста, в твою секту я не вступлю.
Кстати, а какие профиты у кложуроскрипта перед js? Обработка sparse data, с которой проблемы у типосектантов, в js не является чем-то затруднительным. Макросы? Есть сахарок, если сильно надо. Иммутабельность? Ее нет, но ее легко эмулировать. Figwheel+re-frame? React+redux тоже состояние не теряют, работать удобно.
>рефакторить тысячи строк кода без единого теста
Ээ... ты о чем?
> Кстати, а какие профиты у кложуроскрипта перед js?
1 + "2" уже посчитал?
> Макросы? Есть сахарок, если сильно надо.
Что ты несешь, какой сахарок? Макросы нужны, чтобы core.async, спек и тайпчекер сделать подключаемыми либами, а не ждать джвадцать лет es6 тащить все это говно в язык.
> Иммутабельность? Ее нет, но ее легко эмулировать.
Смешно. Это сразу делает очевидным тот факт, что ты не писал ничего как минимум на функциональных языках, а потому не можешь сравнивать объективно. Из разряда "В ассемблере тоже иммутабельность легко эмулировать))00))".
> React+redux тоже состояние не теряют
Ну так редукс по-твоему чем вдохновлялся? Оригинал, тем не менее, по-прежнему лучше. Если сумеешь все это говно настроить, ахахахахахаха
>Алсо, тайпклассы - зло.
Нет. Вполне рабочий инструмент. Едиственный момент - не надо путать тайпклассы с интерфейсами из ООП, например. Интерфейс - это набор методов. А тайпкласс - набор прведений.
Тайпкласс - это имплицитная загрузка кода. Неявное поведение == зло. Алсо, ты постом промазал чуток.
Поведение всегда явное, подключение происходить неявно. Не нужно смешивать.
Тайпклассы зарекомендовали себя, как один из лучших паттернов, отличная замена антипаттерну "наследование"
Помню в школе паскаль преподавали, так и говорили.
>Не нужно смешивать.
Ну так вот ты как раз и смешиваешь, разделяя некое магическое ПОДКЛЮЧЕНИЕ и поведение\декларации. В этом и проблема (часть проблемы).
> антипаттерну "наследование"
Тайпклассы - замена наследованию? Please tell me more. Вообще, даже за любое упоминание слова "наследование" итт нужно проводить профилактическое анальное изнасилование, да.
>>097586
Пошел вон из треда.
Два анальных изнасилования этому господину джаварабу.
Хуль вы вообще вспомнили про это наследование? Никто про него не говорит, никто его не сравнивает с тайпклассами. Тайпклассы - говно, а наследование - это даже не говно, это просто преступление против человечества, за такое сжигать живьем в печах освенцима нужно.
Если кто-то еще хоть раз скажет "наследование" в этом треде, я пукну
Полностью с тобой согласен.
Другой пример. Ocaml, все гордятся своими модулями, а на деле в большинстве случаев имитируют тайпклассы, которые только кидают руками. А во влажных мечтах хотят полиморфизма, ждут модульных имплицитов, потому что писать +. и print_string не солидно.
Да, я не джавараб, никогда не писал на джаве, лишь интересовался скалой. Я таки вкатываюсь в окамл, ибо в жизни не хватает точечек и нижних подчеркиваний
Если наследование такое говно, то как ты будешь моделировать объекты, которые в жизни реально друг от друга наследуются (типа person/manager/employee и т д)?
Это и в жизни скорее тайпклассы, чем наследование
>в жизни реально друг от друга наследуются
А вот и ООП-головного-мозга подъехало. И понесло какую-то чушь как и всегда.
Ну, например, так же, как это делают разработчики игровых движков еще с середины 90-ых - с помощью композиции. Но ооп-манька об этом ничего не слышала, у нее же наследование вместо мозга.
В жизни хорошо наследуются только наследства.
> Не обоссывайте
Хорошо, но только если ты пояснишь, каким образом Менеджер наследуется от Человека. Менеджер - это такой биологический подвид человеков, я правильно понял? А Батя - другой подвид, так? То есть у тебя с твоей еотовой может родиться либо Менеджер, либо Батя, ну либо просто абстрактный Чоловiк, так?
Ну не так написал, скорее manager - это подвид employee.
>что у Manager есть поле Employee.
Щито? Нет, у Чоловика есть компоненты Менеджер и Сотрудник.
> неестественно
Классы не предназначены для моделирования предметной области. Если ты используешь классы для домейна, то ты doing it wrong. Классы - это низкоуровневый механизм абстракции состояния. Смешивать уровни абстракции - типикал говноедство.
> А поведение реализуется через тайпклассы.
Через тайпклассы реализуется полиморфизм. Если поведение не предполагает полиморфизма, то и тайпклассы не нужны.
Смотри, как можно сделать то же, что и здесь
https://pastebin.com/T0qJen1Y
без наследования? Если не использовать наследование, то как избежать необходимости определять инстанс тайпкласса для каждого из типов? В хаскеле можно написать deriving(Show), но представь, что у меня не Show, а какой-нибудь тайпкласс, который нельзя автоматически вывести.
Очевидно, что если типы Node, InternalNode и Leaf связаны через композицию, а не через наследование, то компилятор никак не сможет автоматически вывести инстанс тайпкласса. Чтобы вывести, придется для каждого класса бойлерплэйтную хуйню писать:
https://pastebin.com/4FVBNR0W
Или вот так еще можно:
https://pastebin.com/giQNGZCC
Наверное, можно как-то поколдовать, чтобы тайпкласс через метод derive выводился автоматически, но это уже будет жесткая наркомания с неявными преобразованиями, что намного хуже наследования.
Ээ, так кейс-классы - это как бы абсолютно то же самое, что дата в х-ле, просто с нескучным синтаксисом для джава-господмакак, не?
По сути да. Просто подъедет сахарок и можно будет не писать бойлерплейт sealed trait case class case class
https://mitpress.mit.edu/sicp/full-text/book/book-Z-H-10.html
Ниже приведена последовательность выражений. Каков результат, напечатанный интерпретатором в ответ на каждое выражение? Предположим, что последовательность должна быть оценена в том порядке, в котором она представлена.
-- 10
print $ 10
-- (+ 5 3 4)
print $ foldr (+) 0 [5, 3, 4]
-- (- 9 1)
print $ (-) 9 1
-- (/ 6 2)
print $ (/) 6 2
-- (+ ( 2 4) (- 4 6))
print $ (+) (() 2 4) ((-) 4 6)
-- (define a 3)
a :: Int
a = 3
-- (define b (+ a 1))
b :: Int
b = (+) a 1
-- (+ a b ( a b))
print $ foldr (+) 0 [a, b, (() a b)]
-- (= a b)
print $ (==) a b
-- (if (and (> b a) (< b ( a b)))
-- b
-- a)
print $ if (&&) ((>) b a) ((<) b (() a b)) then b else a
-- (cond ((= a 4) 6)
-- ((= b 4) (+ 6 7 a))
-- (else 25))
cond :: Int
cond | (==) a 4 = 6
| (==) b 4 = foldr (+) 0 [6, 7, a]
| otherwise = 25
-- (+ 2 (if (> b a) b a))
print $ (+) 2 (if (>) b a then b else a)
-- ( (cond ((> a b) a)
-- ((< a b) b)
-- (else -1))
-- (+ a 1))
cond :: Int
cond = () x ((+) a 1) where
x | (>) a b = a
| (<) a b = b
| otherwise = -1
Ниже приведена последовательность выражений. Каков результат, напечатанный интерпретатором в ответ на каждое выражение? Предположим, что последовательность должна быть оценена в том порядке, в котором она представлена.
-- 10
print $ 10
-- (+ 5 3 4)
print $ foldr (+) 0 [5, 3, 4]
-- (- 9 1)
print $ (-) 9 1
-- (/ 6 2)
print $ (/) 6 2
-- (+ ( 2 4) (- 4 6))
print $ (+) (() 2 4) ((-) 4 6)
-- (define a 3)
a :: Int
a = 3
-- (define b (+ a 1))
b :: Int
b = (+) a 1
-- (+ a b ( a b))
print $ foldr (+) 0 [a, b, (() a b)]
-- (= a b)
print $ (==) a b
-- (if (and (> b a) (< b ( a b)))
-- b
-- a)
print $ if (&&) ((>) b a) ((<) b (() a b)) then b else a
-- (cond ((= a 4) 6)
-- ((= b 4) (+ 6 7 a))
-- (else 25))
cond :: Int
cond | (==) a 4 = 6
| (==) b 4 = foldr (+) 0 [6, 7, a]
| otherwise = 25
-- (+ 2 (if (> b a) b a))
print $ (+) 2 (if (>) b a then b else a)
-- ( (cond ((> a b) a)
-- ((< a b) b)
-- (else -1))
-- (+ a 1))
cond :: Int
cond = () x ((+) a 1) where
x | (>) a b = a
| (<) a b = b
| otherwise = -1
Макаба сожрала звездочки же. Пастебин пасти. Алсо, мне кажется, или в последнем ты что-то намудрил?
М, и правда сожрала. Завел фейкогитхабчик, буду туда постить - https://github.com/functional-experiments/sicp/blob/master/exercise_1.01.hs
> Алсо, мне кажется, или в последнем ты что-то намудрил?
Ага, перевожу там лисповый cond в guards, но не знаю, как guards записать inline (это вообще возможно?). Поэтому вынес весь cond в отдельный where - https://github.com/functional-experiments/sicp/blob/master/exercise_1.01.hs#L23
Перевести следующее выражение в префиксную форму
https://github.com/functional-experiments/sicp/blob/master/exercise_1.02.hs
На х-ле это, конечно, выглядит инфернально.
Чего-то пока не определился с отступами, какие-то неочевидные требования к ним в .hs файлах.
Упражнение 1.3.
Определите процедуру, которая принимает три числа в качестве аргументов и возвращает сумму квадратов двух наибольших чисел.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.03.hs
> sqsum1 a b c = res where
> ...
> res = foldr (+) 0 squared
АСТАНАВИТЕСЬ
используй комбинаторы, если хочешь писать в порядке исполнения
Смысл в том, чтобы научиться что-нибудь писать, а затем понять, как писать это "идиоматически". Пока намеренно префиксные операторы использую, чтобы было больше похоже на схему.
Ну и первые примеры в SICP - helloworld'ы, далее должно интереснее стать.
>>106949
Спс, прочитал вот это https://wiki.haskell.org/Combinator уже раза 4 и пока не вкурил, что это. Пойду LYAH полистаю.
>>106955
По первой ссылке - неясно в чем профит, т.е. те же самые операции можно одной строкой записать, но зачем? В математике - 1 преобразование на 1 строку же. По второй - пока ничего не понял, это похоже на какой-то хитроприготовленный JS вроде https://github.com/sanctuary-js/sanctuary
Заметим, что наша модель исполнения позволяет комбинации, операторы которых являются составными выражениями. Используйте это наблюдение для описания поведения следующей процедуры:
(define (a-plus-abs-b a b)
((if (> b 0) + -) a b))
https://github.com/functional-experiments/sicp/blob/master/exercise_1.04.hs
Комбинаторы == функции высшего порядка. Я имел в виду |>.
Дело не в одной строке (записывай в несколько, если хочешь), а в абсолютно лишних и засоряющих код именах. f x = foo where foo = bar - это вообще из серии if x is true then true else false.
По второй - абсолютно тот же самый код, что с точками, просто композиция идет в том порядке, в котором этот код будет выполняться (слева направо) - точно так же, как у тебя с именами. Примерно то же, что -> в кложе и |> в эликсире (ну и в окамле\эфшарпе, конечно).
С точечкой (композицией) или долларом (аппликацией) ты пишешь функции в том же порядке, в каком писал бы их со скобочками:
h $ g $ f $ x == h(g(f x))
Сперва выполняется f x, потом к результату применяется g, потом к этому результату применяется h.
С пайпострелочкой ты пишешь функции в том же порядке, в котором они применяются:
x |> f |> g |> h
Сперва выполняется f x, потом к результату применяется g, потом к этому результату применяется h.
Это просто аппликация, в которой аргумент слева от функции:
( $ ) f x = f x
( |> ) x f = f x
x |> f == f $ x == f x
Эх, поставить х-ль да присоединиться к тебе, что ли?
Господи, что за наркомания? Оно вообще компилируется?
aPlusAbsB a b = (if b > 0 then (+) else (-)) a b
Аргументировал же уже где-то там выше. Неявное поведение, нелокальные эффекты, глобальное состояние of sorts.
Почему бы не писать сразу нормально? Ну, например, очевидно, что foldr для простых арифметических операций нахуй не нужен, что в cond'е потребности нет в виду наличия guard'ов и т.д.
Т.е. это такой оператор "задом-наперед":
(|>) :: a -> (a -> b) -> b
a |> b = b a
Классно, конечно, что можно синтаксис менять так просто, но я пока стараюсь максимально прямолинейно писать.
Про $ и . почитал LYAH - http://learnyouahaskell.com/higher-order-functions#function-application , оттуда:
> Хорошо, потому что $ является право-ассоциативным, f (g (z x)) равно f $ g $ z x. Итак, мы можем переписать
>
> sum (filter (> 10) (map (2) [2..10]))
>
> в виде
>
> sum $ filter (> 10) $ map (2) [2..10]
Это какое-то проявление ненависти к скобкам/лиспу? Запись только скобками отличается же. И с "." аналогично. Ну т.е. синтаксический сахар - это хорошо, но я пока продолжу в стиле "императивное быдло, сэр" писать.
Я как понимаю, такая гибкость синтаксиса далее с более сложными конструкциями пригодится, но до них еще не дошел.
>Ну, например, очевидно, что foldr для простых арифметических операций нахуй не нужен
Хм, а как тогда ближе всего к схеме записать вот это:
(+ 6 7 a)
Вот такой фолдр наиболее близким выглядит:
foldr (+) 0 [6, 7, a]
Понятно, что "6 + 7 + a" тоже сработает, но в схеме это list же, а не просто 3 значения.
Про cond - согласен.
Нет там списка, по крайней мере явно. Ну и блджад, кто ж дословно-то переводит?
>(+ 6 7 a)
6 + 7 + a
>(fold-right + (list 6 7 a))
А вот тут есть список.
Как он у тебя появится, если тебе нужно конкретную функцию написать? Хуйней не страдай, ммкей? Если нужно использовать матч - используй матч (только нормальный матч, а не ту наркоманию, которую ты там нагородил), если нужно использовать иф - используй иф.
>>107222
>"задом-наперед":
Ну, ээ, наоборот. Обычная композиция\аппликация - задом наперед (в начале - последняя операция, в конце - первая), поэтому и нужен или ненужен |>.
> можно синтаксис менять так просто
Это не имеет к синтаксису никакого отношения, это просто обычная функция. Вот поэтому, кстати, сикп и использует scheme - чтобы не возникало путаницы с этими понятиями.
> Это какое-то проявление ненависти к скобкам/лиспу?
Возможно, лол. На самом деле просто плоские линейные последовательности читать проще, чем вложенные древовидные. В лиспах это тоже есть (и с правильным порядком по умолчанию, слева-направо).
> я пока продолжу в стиле "императивное быдло, сэр" писать.
Извини конечно, но ты пока пишешь в стиле "я обдолбался добом, засунул дилду в себе анус и пошел танцевать". Я же выше кидал https://pastebin.com/raw/7KbL980B пример того, как надо выравнивать и писать гарды - а ты все равно не выравниваешь и пишешь foo x = y where y = z.
Не, ну тут тащем-то его интент вполне понятен. Но все-таки да, 6 + 7 + a лучше - и главное ближе к оригиналу.
Наиболее близкий и наиболее близким ВЫГЛЯДИТ - это все-таки очень разные вещи (вторая - бесполезнее).
С заимствованием терминов, названий новых вещей ещё можно смириться, но вытеснение инородными обычных разговорных слов выглядит просто отвратительно. Примерно так же, как foldr (+) или cond в коде того анона.
>названий новых вещей
>вагина
Ололо, девственники в треде!
К тому же, это тоже термин. Вот, например: https://ru.wikipedia.org/wiki/Интент-анализ
Алсо, я не уверен, какое слово ты предлагаешь использовать вместо. "Намерение" не совсем подходит.
>но вытеснение инородными обычных разговорных слов выглядит просто отвратительно
Изи-изи, эт не рил ток, синк эбаут ит, мэн.
Посмотрел еще раз код, я понял в чем проблемы.
С foldr (+) ... - вместо обычной суммы. Это намеренно делается. Обычная сумма и из Java-бекграунда нормально воспринимается. А foldr и прочие ф-циональные записи, более сложные, чем простой map (ололо - Guava) - вводят в ступор и на них надо минуту смотреть, пока поймешь в чем дело. Поэтому буду продолжать всюду foldr'ы использовать, чтобы мозжечок привыкал их читать.
С where похожая ситуация, если функция вот так записана:
fun1 :: Int -> Int -> Int
fun1 a b = res where
...
res =...
То сознание, искалеченное Жабой (и Скриптом), автоматически переводит это в:
static int fun1(int a, int b) {
...
return ...
}
А если записано вот так:
fun1 :: Int -> Int -> Int
fun1 0 b = 42
fun1 1 b = ...
fun1 a 42 = ...
то парсер сразу падает с ошибкой (функция перегружена некорректно лол). Поэтому, несмотря на эстетические чувства окружающих, буду дальнейшие примеры также делать.
А выравнивание гардов - учел.
Посмотрел еще раз код, я понял в чем проблемы.
С foldr (+) ... - вместо обычной суммы. Это намеренно делается. Обычная сумма и из Java-бекграунда нормально воспринимается. А foldr и прочие ф-циональные записи, более сложные, чем простой map (ололо - Guava) - вводят в ступор и на них надо минуту смотреть, пока поймешь в чем дело. Поэтому буду продолжать всюду foldr'ы использовать, чтобы мозжечок привыкал их читать.
С where похожая ситуация, если функция вот так записана:
fun1 :: Int -> Int -> Int
fun1 a b = res where
...
res =...
То сознание, искалеченное Жабой (и Скриптом), автоматически переводит это в:
static int fun1(int a, int b) {
...
return ...
}
А если записано вот так:
fun1 :: Int -> Int -> Int
fun1 0 b = 42
fun1 1 b = ...
fun1 a 42 = ...
то парсер сразу падает с ошибкой (функция перегружена некорректно лол). Поэтому, несмотря на эстетические чувства окружающих, буду дальнейшие примеры также делать.
А выравнивание гардов - учел.
Бен Битдидл изобрел тест, чтобы определить, с каким интерпретатором он сталкивается, использует оценку аппликативного порядка или оценку нормального порядка. Он определяет следующие две процедуры:
(define (p) (p))
(define (test x y)
(если (= x 0)
0
у))
Затем он оценивает выражение
(тест 0 (p))
Какое поведение Бена будет наблюдать с помощью интерпретатора, который использует оценку аппликативного порядка? Какое поведение он будет наблюдать с помощью интерпретатора, который использует оценку нормального порядка? Поясните свой ответ.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.05.hs
Здесь подвох вот в этой функции:
p :: Int
p = p
Удивился немного, когда она скомпилилась. Вопрос предполагает, что при нормальном порядке вычисления, интерпретатор повиснет на раскрытии p = p, а при аппликативном - не дойдет до него. Так как if/guard в хаскеле - short-circuting, то p никогда не выполнится (dead code elimination все дела).
Что интересно, "test p 0" успешно вешает runghc - ленивость не помогает.
Бен Битдидл изобрел тест, чтобы определить, с каким интерпретатором он сталкивается, использует оценку аппликативного порядка или оценку нормального порядка. Он определяет следующие две процедуры:
(define (p) (p))
(define (test x y)
(если (= x 0)
0
у))
Затем он оценивает выражение
(тест 0 (p))
Какое поведение Бена будет наблюдать с помощью интерпретатора, который использует оценку аппликативного порядка? Какое поведение он будет наблюдать с помощью интерпретатора, который использует оценку нормального порядка? Поясните свой ответ.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.05.hs
Здесь подвох вот в этой функции:
p :: Int
p = p
Удивился немного, когда она скомпилилась. Вопрос предполагает, что при нормальном порядке вычисления, интерпретатор повиснет на раскрытии p = p, а при аппликативном - не дойдет до него. Так как if/guard в хаскеле - short-circuting, то p никогда не выполнится (dead code elimination все дела).
Что интересно, "test p 0" успешно вешает runghc - ленивость не помогает.
>С foldr (+) ... - вместо обычной суммы.
Тебе просто говорят, что (+ 1 2 3) - это не то же самое, что foldr (+) [1 2 3], а ты вроде как думал, что это то же самое, что неверно.
Второй поинт не уловил. Раз парсер на той записи падает с ошибкой, то надо же как раз и упражнять мозжечок на эту запись, чтоб он не падал, не?
>>107439
В четвертый раз говорю, что для гардов не нужен where. Зачем ты там "res" написал? Еще раз посмотри на cmp1 здесь: https://pastebin.com/raw/7KbL980B
И сравни с https://github.com/functional-experiments/sicp/blob/master/exercise_1.05.hs#L26
Зачем ты там res написал?
Прочитай "Guards, guards!" в http://learnyouahaskell.com/syntax-in-functions
Опять же, поэтому сикп и использует схемку с минимумом синтаксиса.
>>107439
Алсо, я не понял, ты через гугл транслейт текст прогоняешь, лол? Нахуя? Какая еще "оценка аппликативного порядка", лол? У сикпа есть замечательный русский перевод, если что.
>>107439
>Так как if/guard в хаскеле - short-circuting, то p никогда не выполнится (dead code elimination все дела).
If\guard в хаскеле не short-circuiting, в х-ле все вычисления ленивые. Ни ифы, ни гарды тут ни при чем. С dead code elimination это тоже не имеет ничего общего. Это техника оптимизации выхлопа компилятора, к порядку исполнения не имеет вообще никакого отношения.
> Что интересно, "test p 0" успешно вешает runghc
Потому что ты аргументы местами перепутал, должно быть test 0 p.
> Здесь подвох вот в этой функции:
- это не функция.
Еще одна причина, по которой в сикп используется схемка, лол.
>Зачем ты там res написал?
См подробно тут >>107436 , это такая фича.
>>107454
>Алсо, я не понял, ты через гугл транслейт текст прогоняешь, лол? Нахуя? Какая еще "оценка аппликативного порядка", лол?
Это чтобы мимокрокодилы не пугались от вида простыней на нерусском. Ссылку на оригинал SICP, откуда копипастю, постил выше.
"оценка аппликативного порядка" - классный термин по-моему, надо будет его рекомендовать всем, кто в ФП вкатывается, как "первое, что надо в ФП изучить".
> У сикпа есть замечательный русский перевод, если что.
А он есть в открытом доступе? Что-то не гуглится, а то буду оттуда копипастить.
>>107461
Лол, а что это? Я думал в хаскеле все что в таком же виде как функция объявляется - все будет функцией.
Алисса П. Хакер не понимает, почему, если нужно предоставить специальную форму. «Почему я не могу просто определить его как обычную процедуру с точки зрения cond?», - спрашивает она. Друг Алиссы Эва Лу Атор утверждает, что это действительно можно сделать, и она определяет новую версию if:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
Ева демонстрирует программу для Алиссы:
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
Delighted, Alyssa использует new-if, чтобы переписать программу с квадратным корнем:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
Что происходит, когда Алисса пытается использовать это для вычисления квадратных корней? Объясните.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.06.hs
А вот на этом упражнении я подвис. После гугления понял, что в схеме у встроенного if и самописного if будут разные правила выполнения. Вроде как short-circuit https://en.wikipedia.org/wiki/Short-circuit_evaluation не должно быть у самописного if. В комментариях к читам sicp по этому поводу срач - http://community.schemewiki.org/?sicp-ex-1.6
В итого сделал через лямбды, чтобы в моем самописном if точно было все лениво.
Перечитал wiki, про short-circuit условие неправильно написал (он не влияет), это then и else должны по разному выполняться.
>См подробно тут >>107436 , это такая фича.
АААААААА СУКА БЛЯДЬ ТЫ ИЗДЕВАЕШЬСЯ НАХУЙ?! КАКАЯ НАХУЙ ФИЧА, Я ТЕБЕ УЕБУ СЕЙЧАС, БЛЯДЬ! ТЫ ТАМ ПИШЕШЬ ПРО КУСОЧНЫЕ ФУНКЦИИ, А Я ТЕБЯ ГОВОРЮ ПРО ГАРДЫ! СУКА, БЛЯДЬ! ИЗДЕВАЕШЬСЯ, СУУУКААА?! https://github.com/functional-experiments/sicp/blob/master/exercise_1.05.hs#L26 ВОТ ЗДЕСЬ ТОЧНО ТОТ ЖЕ САМЫЙ КОД БЛЯДЬ БУДЕТ, БЕЗ КУСОЧНЫХ ФУНКЦИЙ, С ТЕМИ ЖЕ САМЫМИ ГАРДАМИ, БЛЯДЬ, ТОЛЬКО БЕЗ WHERE, ПОТОМУ ЧТО БЛЯДЬ ТЫ ВОЗВРАЩАЕШЬ RES И СРАЗУ ЖЕ ГАРДЫ НА НЕГО ВЕШАЕШЬ, БЛЯДЬ, ПРОСТО УБЕРИ RES WHERE \N RES, ГАРДЫ ОСТАНУТСЯ ТАМ ЖЕ, ЭТО НЕ КУСОЧНАЯ ФУНКЦИЯ, БЛЯДЬ, RES WHERE RES ЭТО ТО ЖЕ САМОЕ, ЧТО IF X == TRUE THEN TRUE ELSE FALSE, БЛЯЯДЬ, КАК ЖЕ МНЕ ОТ ТЕБЯ БОМБИТ, СУКА БЛЯДЬ ПИЗДЕЦ, ААААААААА
>Это чтобы мимокрокодилы не пугались от вида простыней на нерусском.
Ну, английский-то в х-ль-треде все, думаю, знают.
>"оценка аппликативного порядка" - классный термин по-моему, надо будет его рекомендовать всем
Ээ, лол, жестокий ты.
> А он есть в открытом доступе?
http://newstar.rinet.ru/~goga/sicp/sicp.pdf
> все что в таком же виде как функция объявляется
Ну так функция объявляется в виде f x = ..., а у тебя x = ...
Все функции принимают ровно один аргумент, ты это в типах видишь (стрелочки там не просто так).
p = p - это просто значение (как x = 42), но благодаря ленивости мы его можем определять рекурсивно в терминах самого себя. Например:
xs = [1] ++ xs -- бесконечный список: [1, 1, 1, ...]
take 3 xs -- из которого можно брать элементы: [1, 1, 1]
>В итого сделал через лямбды
Чувак, но это же значит, что ты не понимаешь, как работает ленивость в х-ле - то есть как раз материал этой главы, понимание которого и призвано проверить данное упражнение.
>Чувак, но это же значит, что ты не понимаешь, как работает ленивость в х-ле
Возможно оно так и есть, навскидку, не обращаясь к LYAH (и игнорируя IO):
1. вся программа в хаскеле представляет собой цепочку вызовов функций, например map(fold(input_list)), только очень длинную
2. эта цепочка хаскель-рантаймом преобразуется в набор thunks (кусков (байт)кода в intermediate representation виде без входных параметров)
3. эти thunks рантайм расставляет в какой-то неочевидной последовательности (те, что не нужны для результата - выбрасывает) и далее выполняет 1 за другим
Это похоже на правду?
Не, не только фибонначчи, еще и аккерман можно EJB писать, деплоить их на апп-сервера и считать фибоначчи через hadoop и не тормозить - https://github.com/typelead/eta
Чистый, понятный и хорошо структурированный код же, что тебе не нравится, в Java все так делают - http://shitcode.net/135
>Чистый, понятный и хорошо структурированный код
>Используется concrete класс
мы вам перезвоним
Тушись и возвращайся обратно в свой пхп-тред, дружочек :3
>>107894
> foreign import java unsafe "@static java.lang.System.getenv"
> getEnv :: String -> IO (Maybe String)
Смищно. Ненужно. Скалка.
>>107893
Ну, только не цепочка, а граф, и не вызовов функций, а сразу тханков, и вообще я намекал тебе на то, что раз ты оборачиваешь там выше аргументы к ифу в лямбды, то ты не понял, чем нормальный порядок от аппликативного отличается.
> раз ты оборачиваешь там выше аргументы к ифу в лямбды, то ты не понял, чем нормальный порядок от аппликативного отличается
Код для этого примера писал несколько дней назад, с тех пор еще пару раз перечитал первую главу и стало вроде попрозрачнее.
Вроде как в нормальном порядке все выражение сразу раскрывается в дерево и потом снизу вверх вычисляется по нодам. И это какая-то теоретическая хрень, которую не использует никто.
А "оценка аппликативного порядка" - это примерно как в пролетарских ЯП - для каждого выражения сначала вычисляем его агументы по очереди, а затем к результатам применяем оператор.
Но вцелом - па-па-памедленнее, вот отсюда >>107746 рекурсивность я пока еще не вкурил, и вообще эта ленивость пока тяжело воспринимается.
> все выражение сразу раскрывается в дерево
При чем тут деревья какие-то, откуда ты это вообще взял? Аппликативный - при вызове вида (f x y z ...) сперва вычисляются x y z..., потом возвращается результат выражения. Нормальный - при вызове вида (f x y z ...) аргументы x y z... могут не вычислиться; сперва применяется f, а аргументы ей передаются "как есть", невычисленными. Вот и вся разница. Деревья там под капотом или не деревья - это уже зависит от реализации.
https://cs.stackexchange.com/questions/40758/difference-between-normal-order-and-applicative-order-evaluation
Scheme is an applicative-order language, namely, that all the arguments to Scheme procedures are evaluated when the procedure is applied. In contrast, normal-order languages delay evaluation of procedure arguments until the actual argument values are needed.
>И это какая-то теоретическая хрень, которую не использует никто.
> сам же пишет на хаскелле
Ну пиздец!
> "оценка аппликативного порядка"
Какая оценка, блядь? Аппликативный порядок выполнения (evaluation).
>рекурсивность я пока еще не вкурил, и вообще эта ленивость пока тяжело воспринимается.
Рекурсивные значения - достаточно мозгоебная хрень, да. Тут как раз проще подумать о реализации (точнее некотором приближении того, как это может быть реализовано).
Грубо говоря, представь, что каждый top level definition у тебя создает граф, в котором ноды - это подвыражения в этом дефинишне. То есть как раз примерно то, о чем ты как раз читал в сикпе. И когда ты пишешь p = p, то это просто создает тривиальный граф, в котором только одна нода и только одно ребро, которое выходит из этой ноды и входит в эту же ноду. То есть простейший циклический граф. Соответственно, если ты используешь этот p в каком-то другом объявлении (которое тоже граф), то этот цикл подцепится и туда. Грубо говоря, если напишешь x = (+) 1 p, то у тебя будет граф с вершиной (+), от которой идут два ребра: одно - в вершину "1", а другое - в вершину "p", от которой идет ребро в саму себя. Вот нарисуй сейчас, со стрелочками. То есть получается, что, вычисляя все выражение (то есть следуя по стрелочкам), ты навсегда застрянешь в зацикленной вершине p.
А когда ты пишешь xs = [1] ++ xs, то цикл в графе, грубо говоря, "накачивает" вершину новыми значениями, но всегда оставляет то же самое (циклическое) ребро. То есть представь, что ты запустил в дебаггере выражение xs = [1] ++ xs и смотришь, как граф меняется с каждым шагом. Сперва у тебя в вершине [1], и ребро выходит из этой вершины и входит в нее же. На самом деле там не ребро, а подграф вида (++ [1] (++ [1] ...), который будет расти c каждым шагом - но мы для простоты считаем, что у нас умный рантайм, который на каждом шаге схлопывает этот подграф в одну вершину с циклом. Ты делаешь один шаг по стрелочке, приходишь опять в эту же вершину, но теперь в ней уже значение [1, 1]. Еще щаг - [1, 1, 1]. И так далее, можешь делать столько шагов, сколько хочешь - до конца оно никогда не вычислится, ибо это цикл в графе. А take 3 xs можешь считать как раз эдаким "пошаговым дебагером", который заходит в вершину xs, делает столько шагов, сколько указано в первом аргументе (то есть 3 шага), и потом возвращает то значение вершины, которое у нас получилось после этих шагов (уже без цикла!).
Как-то так, если грубо.
>рекурсивность я пока еще не вкурил, и вообще эта ленивость пока тяжело воспринимается.
Рекурсивные значения - достаточно мозгоебная хрень, да. Тут как раз проще подумать о реализации (точнее некотором приближении того, как это может быть реализовано).
Грубо говоря, представь, что каждый top level definition у тебя создает граф, в котором ноды - это подвыражения в этом дефинишне. То есть как раз примерно то, о чем ты как раз читал в сикпе. И когда ты пишешь p = p, то это просто создает тривиальный граф, в котором только одна нода и только одно ребро, которое выходит из этой ноды и входит в эту же ноду. То есть простейший циклический граф. Соответственно, если ты используешь этот p в каком-то другом объявлении (которое тоже граф), то этот цикл подцепится и туда. Грубо говоря, если напишешь x = (+) 1 p, то у тебя будет граф с вершиной (+), от которой идут два ребра: одно - в вершину "1", а другое - в вершину "p", от которой идет ребро в саму себя. Вот нарисуй сейчас, со стрелочками. То есть получается, что, вычисляя все выражение (то есть следуя по стрелочкам), ты навсегда застрянешь в зацикленной вершине p.
А когда ты пишешь xs = [1] ++ xs, то цикл в графе, грубо говоря, "накачивает" вершину новыми значениями, но всегда оставляет то же самое (циклическое) ребро. То есть представь, что ты запустил в дебаггере выражение xs = [1] ++ xs и смотришь, как граф меняется с каждым шагом. Сперва у тебя в вершине [1], и ребро выходит из этой вершины и входит в нее же. На самом деле там не ребро, а подграф вида (++ [1] (++ [1] ...), который будет расти c каждым шагом - но мы для простоты считаем, что у нас умный рантайм, который на каждом шаге схлопывает этот подграф в одну вершину с циклом. Ты делаешь один шаг по стрелочке, приходишь опять в эту же вершину, но теперь в ней уже значение [1, 1]. Еще щаг - [1, 1, 1]. И так далее, можешь делать столько шагов, сколько хочешь - до конца оно никогда не вычислится, ибо это цикл в графе. А take 3 xs можешь считать как раз эдаким "пошаговым дебагером", который заходит в вершину xs, делает столько шагов, сколько указано в первом аргументе (то есть 3 шага), и потом возвращает то значение вершины, которое у нас получилось после этих шагов (уже без цикла!).
Как-то так, если грубо.
Добра тебе, анон. Твоя ссылка заставила перечитать про порядок выполнения не только в SICP (где описание многословное и бестолковое), но и другие источники. В итоге все прояснилось после вот этой статьи из "википедии для олдфагов" - http://wiki.c2.com/?LazyEvaluation
аппликативный (пример: java) - аргументы вычисляются единожды перед вызовом
нормальный (пример: boost.preprocessor) - аргументы передаются в вызов невычисленными и вычисляются каждый раз, когда понадобятся
ленивый (пример: haskell) - аргументы передаются в вызов невычисленными, когда понадобятся - вычисляются единожды и запоминаются, при последующих обращениях используется запомненное значение
Сделал
git reset --hard >>107686
и ушел решать заново пример про Алиссу П. Хакер
Лиза П. Хакер не понимает, почему if должна быть особой формой. «Почему нельзя просто определить ее как обычную процедуру с помощью cond?» — спрашивает она.
Лизина подруга Ева Лу Атор утверждает, что, разумеется, можно, и определяет новую версию if:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
Ева показывает Лизе новую программу:
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
Обрадованная Лиза переписывает через new-if программу вычисления квадратного корня:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
Что получится, когда Лиза попытается использовать эту процедуру для вычисления квадратных
корней? Объясните.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.06.hs
haskell использует какую-то особую уличную магию ленивое вычисление и позволяет передать невычисленную рекурсивную функцию, возвращающую Float, в качестве Float параметра. В пролетарских языках в таком случае надо будет передавать замыкание и явно его вызывать где-нужно.
Лиза П. Хакер не понимает, почему if должна быть особой формой. «Почему нельзя просто определить ее как обычную процедуру с помощью cond?» — спрашивает она.
Лизина подруга Ева Лу Атор утверждает, что, разумеется, можно, и определяет новую версию if:
(define (new-if predicate then-clause else-clause)
(cond (predicate then-clause)
(else else-clause)))
Ева показывает Лизе новую программу:
(new-if (= 2 3) 0 5)
5
(new-if (= 1 1) 0 5)
0
Обрадованная Лиза переписывает через new-if программу вычисления квадратного корня:
(define (sqrt-iter guess x)
(new-if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x)))
Что получится, когда Лиза попытается использовать эту процедуру для вычисления квадратных
корней? Объясните.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.06.hs
haskell использует какую-то особую уличную магию ленивое вычисление и позволяет передать невычисленную рекурсивную функцию, возвращающую Float, в качестве Float параметра. В пролетарских языках в таком случае надо будет передавать замыкание и явно его вызывать где-нужно.
> square1(guess)
Шта? Применение функции - f x, а не f(x). Скобки - только для группировки (изменения приоритета). То есть это то же, что и abs1(square1 guess - x) < 0.001. Со всеми скобками: (abs1 ((square1 guess) - x)) < 0.001
Минимальный набор: abs1 (square1 guess - x) < 0.001
В остальном - все ок.
Разве что еще можно настроить редактор, чтобы он выравнивал объявления:
| a >= 0 = a
| otherwise = (-a)
Макаба наверное проебет, но тыпонел.
Ну если для тебя это новое и нечитаемое, желаю скорейшего заполнения пустот в знаниях, иначе стыдно называть себя программистом в 21 веке.
Объясните мне, зачем надо было вводить тайпклассы? SPJ не осилил старую-добрую перегрузку, как в C++? Нет, я правда не понимаю.
Да потому что, блядь, нормальной модели рантайма нет. Только гуманитарные словоблудия, как у ван Россума в доке. f x y - и догадайся, мол, сама, во что эта хуйня выльется и сколлько тактов займет. Бесит!
> "оценка аппликативного порядка" - классный термин по-моему
А как же КЛАСТЕРЫ МЕТАПАРАДИГМ? Хотя этим вроде лисперы баловались, у них-то язычок погибче будет.
>старую-добрую перегрузку, как в C++
ссаное говно потому что
без тайпклассов:
sum :: [a] -> a
с тайпклассами:
sum :: (Num a) => [a] -> a
смекаешь? По сигнатуре видно что sum работает не с любым a
Так ведь если я подсуну ей [NonNum], она все равно не скомпилится, не? Ошибка только будет малопонятной. И ради понятной ошибки стоило отказываться от краткости кода? Или как?
Ты действительно считаешь, что ограничение на тип влияет на краткость кода? То, что ты бы раньше писал в комментах ко входным параметрам функции (а если не писал, то вон из проффесии), теперь ты пишешь в сигнатуре.
https://en.wikipedia.org/wiki/Expression_problem
http://wiki.c2.com/?ExpressionProblem
http://homepages.inf.ed.ac.uk/wadler/topics/type-classes.html#class
http://learnyouahaskell.com/types-and-typeclasses
http://book.realworldhaskell.org/read/using-typeclasses.html
https://wiki.haskell.org/OOP_vs_type_classes
https://wiki.haskell.org/Typeclassopedia
Верно и обратное. Теперь для любой перегрузки, для которой имя функции совпало чисто случайно, нужно писать тайпкласс:
[code]
get :: Form -> FieldID -> String
get :: Car -> ShowmeterID -> Float
[/code]
Либо писать префиксы (Form.get и Car.get). Либо отказываться от перегрузок вообще (привет lift, liftM, liftM2, liftM_ и т. д.).
По скобкам - согласен, дальше поправлю. По отступам - свой супер-стабильный .vimrc не хочу трогать.
Упражнение 1.7.
Проверка good-enough?, которую мы использовали для вычисления квадратных корней, будет
довольно неэффективна для поиска квадратных корней от очень маленьких чисел. Кроме того, в
настоящих компьютерах арифметические операции почти всегда вычисляются с ограниченной точ-
ностью. Поэтому наш тест оказывается неадекватным и для очень больших чисел. Альтернативный
подход к реализации good-enough? состоит в том, чтобы следить, как от одной итерации к дру-
гой изменяется guess, и остановиться, когда изменение оказывается небольшой долей значения
приближения. Разработайте процедуру вычисления квадратного корня, которая использует такой
вариант проверки на завершение. Верно ли, что на больших и маленьких числах она работает
лучше?
https://github.com/functional-experiments/sicp/blob/master/exercise_1.07.hs
Этот пример не особо интересный, единственное в нем появляется сигнатура функции вот такая:
:: (Float -> Float -> Float -> Bool) -> Float -> Float -> Float -> Float
в которой явно не хватает уровней абстракции.
>Не нужны.
Пхп-тред вооон там.
> оба неймспейса с одинаково называющимися функциями юзать.
Подумой. Ты походу не понимаешь, что такое неймспейсы.
Ну,вот тебе в продолжение моего предыдущего примера:
get :: Config -> FieldID -> String
get :: Car -> ShowmeterID -> Float
abruptBrake config car =
if get config "autobrakes" = true && get car "speed" > 120.0 then
brakeNahuy car
else
car
Тред читай. Вот тебе пример, где нужны две функции с не связанными друг с другом сигнатурами, но с одинаковым именем. Понятно, что он не компилируется, потому что и Car, и Config надо добавлять в тайпкласс Gettable where get :: .... Вопрос: нахрена так сделано, почему без тайпкласса нельзя?
Пространство имён (англ. namespace) — некоторое множество, под которым подразумевается модель, абстрактное хранилище или окружение, созданное для логической группировки уникальных идентификаторов (то есть имён).
> В твоем маняпримере вообще никакие функции не нужны, достаточно мапов или рекордов.
В моем маняпримере конфиг читается из флешки, где он прошит в бинарном виде, а показания показометров читаются из портов.
Ты так и будешь кичиться своими тайными знаниями новых, более лучших определений общеизвестных терминов или будешь по де съебешь уже из треда? Почему я в C++ могу написать вот такое (и при ошибках типизации оно даже будет корректно показывать, где ошибка), а в Хачки нет?
Потому что С++ - это огромная куча говна, в которую понапихано все, что туда можно было понапихать, и которая дает тебе тысячу и один способ выстрелить себе в ногу, не? Мимокапитаночевидность, ага.
> конфиг читается из флешки, где он прошит в бинарном виде, а показания показометров читаются из портов.
То есть это две разных функции с разным поведением и разными контрактами. Разные сущности должны иметь разные имена. Для работы с уникальными именами умные человечки придумали неймспейсы. В чем твой вопрос?
Тайп-классы нужны для реализации тайп-сейф ад хок полиморфизма, решения експресьон проблем и создания абстракций - выше тебе ссылки дали. Опять же, в чем твой вопрос?
>>109622
Зачем каждая функция не создает себе по тайп-классу, или что? Во-первых, смотри выше (в этом нет никакого смысла), во-вторых - скорее всего сломается вывод типов, в-третьих - это неочевидный и не запрашиваемый юзером рантайм оверхед. Опять же, в чем конкретно вопрос?
> Разные сущности должны иметь разные имена.
Кому должны?
> Тайп-классы нужны для
похуй чего. Да, они позволяют более точно указывать типы, как в примере с sum, но мне это ни в хуй не вперлось сейчас.
> это неочевидный и не запрашиваемый юзером рантайм оверхед
Где ты там рантайм оверхед увидел? Это решается тупым нейм-манглингом.
> В чем твой вопрос?
Почему в Хаскеле запилили ад-хок полиморфизм, но не запилили никакого другого полиморфизма вообще ни в каком виде? В крестах и яве есть перегрузки, но нет ад-хок полиморфизма, как в Хаскеле. В Хаскеле - наоборот, есть ад-хок полиморфизм, но нет перегрузок. Почему нельзя было сделать произвольные перегрузки, а там, где программисту надо, он указывал бы еще и тайпклассы?
В естественных языках, кстати, есть оба вида полиморфизма (омонимы, контекст). Почему нельзя было сделать, как в инглише, например?
Или так: что плохого в неограниченном полиморфизме при наличии средств для ад-хок полиморфизма?
Так понятнее?
Ты кокойто тупой.
Предлагаю тебе для начала осилить вооот эту страничку на википедии.
https://ru.wikipedia.org/wiki/Полиморфизм_(информатика)
Потом возвращаться в тред (лучше не надо).
В твоем примере нет полиморфизма вообще. Просто две разные функции с разными сигнатурами. А раз функции разные, то и называться они должны по-разному.
Ты какой-то тупой.
> Кому должны?
Хорошо, лично тебе разрешаю отныне обозначать символом "0" числа 0 и 1.
> похуй чего.
Дебил, я тебе объяснял, что такое тайп-классы, так как ссылки открыть у тебя мозгов не хватило. Впрочем, вижу, что зря.
> Где ты там рантайм оверхед увидел?
Дебил, речь про тайп-классы на каждую функцию. Ты же даже один абзац на русском прочитать не можешь.
> Почему в Хаскеле запилили ад-хок полиморфизм, но не запилили никакого другого полиморфизма вообще ни в каком виде?
Запилили, дебил ебаный. Какой же ты тупой.
> Почему нельзя
В прошлом посте объяснил, дебил. Перечитывай, пока не дойдет. Спойлер: никогда не дойдет.
> Почему нельзя было сделать, как в инглише
Какой же ты тупой. Иди делай свои лабы и не засоряй тред, пока не прочитаешь все данные тебе ссылки. Спойлер: никогда не прочитаешь, ты слишком тупой.
> Так понятнее?
Да. Все в этом треде поняли, какой ты дебил. Спасибо, до свидания.
> Хорошо, лично тебе разрешаю отныне обозначать символом "0" числа 0 и 1.
Ты когда используешь метод доведения до абсурда, пооверяй хоть, что получается в итоге. Вспоминай, как работают перегрузки в Java. Там если две функции имеют неразличимые сигнатуры, компилятор ругается.
>>> Разные сущности должны иметь разные имена.
>> Кому должны?
> Хорошо, лично тебе разрешаю отныне обозначать символом "0" числа 0 и 1.
Где ты тут видишь хоть слово про перегрузки в Джаве, дебил ебаный? Бери учебник по русскому языку и учись читать.
1. Компилятору и коллеге-программисту.
2. Компилятор все равно будет вынужден декорировать функции, из-за чего будут страдать вообще все, как страдают пользователи плюсоводских блябляотек.
>>109662
>Почему в Хаскеле запилили ад-хок полиморфизм, но не запилили никакого другого полиморфизма вообще ни в каком виде?
Параметрический полиморфизм ты за полиморфизм уже не считаешь?
А перегрузка - это самый что ни на есть адхок полиморфизм.
А я думал, что - это alias для negate, и вычитание числа из функции выглядело бы как (-3) negate, т.е. функция в даном случае (-3), а число - просто -3.
Потому что хаскель мемный язык.
Ad hoc = перегрузка.
Параметрический полиморфизм в этих языках — настолько базовая вещь, что даже не всегда вспоминается.
Отсутствует только третий вид сабтайп-полиморфизм из-за его сложности.
Минус в хаскеле на особом положении. (-3) - это синтаксический сахар для negate 3, а не частично примененный оператор (-).
Смешная шутка.
Упражнение 1.8.
Метод Ньютона для кубических корней основан на том, что если y является приближением к
кубическому корню из x, то мы можем получить лучшее приближение по формуле (прикрилейтед).
С помощью этой формулы напишите процедуру вычисления кубического корня, подобную процедуре для квадратного корня.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.08.hs
Разгребал всякое г-но, что под н.г. накопилось - ынтырпрайз, он бессмысленный и беспощадный. Вроде разгреб, и можно дальше ерундой заниматься.
Каждая из следующих двух процедур определяет способ сложения двух положительных целых
чисел с помощью процедур inc, которая добавляет к своему аргументу 1, и dec, которая отнимает
от своего аргумента 1.
(define (+ a b)
(if (= a 0)
b
(inc (+ (dec a) b))))
(define (+ a b)
(if (= a 0)
b
(+ (dec a) (inc b))))
Используя подстановочную модель, проиллюстрируйте процесс, порождаемый каждой из этих про-
цедур, вычислив (+ 4 5). Являются ли эти процессы итеративными или рекурсивными?
https://github.com/functional-experiments/sicp/blob/master/exercise_1.09.hs
Эта совсем простое, но интереснее предыдущих. Очевидно, что в первом случае рекурсия не хвостовая (так как результат рекурсивного вызова не возвращается из функции) и стек будет пухнуть.
Описание этой фичи забавное:
> большинство реализаций обычных языков (включая Аду, Паскаль и Си) построены так,
> что интерпретация любой рекурсивной процедуры поглощает объем памяти, линейно рас-
> тущий пропорционально количеству вызовов процедуры, даже если описываемый ею про-
> цесс в принципе итеративен. Как следствие, эти языки способны описывать итеративные
> процессы только с помощью специальных«циклических конструкций» вроде do, repeat,
> until, for и while. Реализация Scheme, которую мы рассмотрим в главе 5, свободна
> от этого недостатка.
"Недостатка", лол, это типа быдлокодеры на пролетарских ЯП не умеют в функциях на 1000 строк, из которых 300 - HTML, 200 - SQL, 500 - недоязычок и 0 - комментарии влет определять, что рекурсия хвостовая, поэтому для них придумали for и while костыли. А если сделает рекурсию - то будет "медленна" на самом деле нет, рантайм все оптимизирует. А вот ФП-мастер-раса вписала себе тейл-рекурсию в стандарт и может свободно использовать.
>будет "медленна" на самом деле нет, рантайм все оптимизирует
Шта? TCO не влияет на скорость, он влияет на сложность по памяти. Рантайм тут ни при чем.
Если у тебя происходит алокация стека функции на каждую итерацию, вместо переиспользования, скорость тоже страдает. Если чтобы переделать в хвостовой вариант, нужно передать только число аргументом, это добавит скорости.
Следующая процедура вычисляет математическую функцию, называемую функцией Аккермана.
(define (A x y)
(cond ((= y 0)
((= x 0)
((= y 1)
(else (A
0)
(* 2 y))
2)
(- x 1)
(A x (- y 1))))))
Каковы значения следующих выражений?
(A 1 10)
(A 2 4)
(A 3 3)
Рассмотрим следующие процедуры, где A — процедура, определенная выше:
(define (f n) (A 0 n))
(define (g n) (A 1 n))
(define (h n) (A 2 n))
(define (k n) (* 5 n n))
Дайте краткие математические определения функций, вычисляемых процедурами f, g и h для
положительных целых значений n. Например, (k n) вычисляет 5n2 .
https://github.com/functional-experiments/sicp/blob/master/exercise_1.10.hs
Сраный Аккерман, ненавижу этого еврея, на функции (h n) сломал мозг и подсмотрел ответ в решенияx.
>Рантайм тут ни при чем.
Имелось ввиду, что рантайм Java/JS/PHP на этапе JIT-компиляции перепишет нахрен всю функцию если сумеет, заинлайнит втруху все что только можно и ТСО на простой цикл заменит но не гарантирует этого, так как не Схема
:%s/ТСО/рекурсивные тейл коллы/g
> foldr нинужын
Точно, это от предыдущей версии осталось, надо поправить.
> cтек не растет - изменяется семантика
Вот хрен знает, эти рантаймы оче много магии содержат. Но пруфоссылок у меня нет. А вообще со стеком разные нехорошие вещи даже C++ разрешает делать (не напрямую связано, но идеи похожие - https://stackoverflow.com/q/47075871/314015 ).
Функция f определяется правилом:
f (n) = n, если n < 3,
и
f (n) = f (n − 1) + f (n − 2) + f (n − 3), если n ≥ 3.
Напишите процедуру, вычисляющую f с помощью рекурсивного процесса. Напишите процедуру, вычисляющую f с помощью итеративного процесса.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.11.hs
Неожиданно подвис на итеративном варианте, оказывается если Фибоначчи сделать не из 2-х элементов, а из 3-х - то задача вдруг становится очень сложной для жабокодеров.
>не напрямую связано, но идеи похожие
Ну, не, я все-таки не сказал бы, что это особо похоже. Все-таки это оптимизация в рамках документированного поведения, причем компилятором. А ты говоришь об изменении структуры кода рантаймом. Насчет магии, конечно, согласен, но, вот если рассуждать дубово: таки никто этого не делает - а значит тому есть какая-то причина.
>>124057
Лол, я сейчас немного подвис. В русском переводе нет коэффицентов 1,2,3 у вызовов f?
> В русском переводе нет коэффицентов 1,2,3 у вызовов f?
Ага, точно, в русском переводе импортозаместили:
f(n) = f(n - 1) + 2f(n - 2) + 3f(n - 3)
на:
f (n) = f (n − 1) + f (n − 2) + f (n − 3)
Приведенная на пикрилейтеде таблица называется треугольником Паскаля (Pascal’s triangle).
Все числа по краям треугольника равны 1, а каждое число внутри треугольника равно сумме двух чисел над ним . Напишите процедуру, вычисляющую элементы треугольника Паскаля с помощью
рекурсивного процесса.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.12.hs
А вот этот пример мне понравился, узнал что для листов 100500 функций есть - https://hackage.haskell.org/package/base-4.10.1.0/docs/Data-List.html
И что листокомпрехеншены есть, прямо как в питоне.
Правда сначала написал решение, а потом прочитал, что нужен рекурсивный способ. Портить итеративный вариант на рекурсивный не стал.
>И что листокомпрехеншены есть, прямо как в питоне.
Вообще-то это в питоне листокомпрехеншены есть, прямо как в сабже
Докажите, что Fib(n) есть целое число, ближайшее к φn / 5, где φ = (1 + 5)/2. Указание: пусть ψ = (1 − 5)/2. С помощью
определения чисел Фибоначчи (см. раздел 1.2.2) и индукции
докажите, что Fib(n) = (φn − ψ n )/ 5.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.13.hs
>Докажите
Ага, как же, не быдлокодерское это дело - теоремы доказывать.
Посчитал в примере для нескольких значений - и правда очень близкие результаты получаются.
Наличие в хаскеле 3-х разных операторов для возведение в степень вызвало некоторое удивление.
Haskell From First Principles 2017 года
зы А ведь я до этого стирал шишку на этот язык.
Байтоеб обезумел, сможешь ли ты совладать с ним?
Я надеюсь, что ты троллишь - в таком случае это тонко и остроумно, снимаю шляпу.
Какой конкретно тип данных нужно записать?
Проблема в том, что Haskell и тот же C - разные языки, для разных целей.
Если C работает с байтами (это грубо сказано, понимаю), то Haskell - с абстракциями вроде функций и монад. Языки для разного, так что не надо орать, что Haskell говно всего лишь из-за этого.
А так ответь на мой вопрос - постараюсь помочь.
Пока вот такое решение:
import Data.ByteString.Builder (hPutBuilder, word32BE)
f :: Word32 -> IO
f = hPutBuilder stdout $ word32BE
>Я просто ебанулся и захотел на хуцкеле писать всё
В этом нет ничего плохого, но ожидать от высокоуровнего языка функций для работы с байтоебством в стандартной библиотеке как-то глупо, не находишь?
Type constructors или datatypes объявляются при помощи `data`. Алиасы - при помощи `type`. Через `:t` можно смотреть тип чего-угодно, кроме тайпклассов. Функции или value constructor-а например. Для typeclasses юзается `:info`
Сейчас многие языки стремятся включить мощные абстракции ФП в стандарт: C++, Java и т. д. Также популярность возросла благодаря таким языкам, как Scala, Go и т. п.
Понимаю, с такими идеями мне сразу в /b/ надо.
Да вы заебали, в одном треде шлюха вниманиеблядит, в другом шмара в оп-посте, теперь еще и сюда эту хуйню ТЯН ТЯН ПИСЕЧКА ТЯН тащат, пиздец просто.
Двачаю. Хаскель - серьезный язык для и серьезных умных людей и это не сарказм. Мы тут ерундой не занимаемся.
А чо в ней такого крутого? Чем лучше "во имя добра"? Реквестирую рецензию, короче.
Хуй сосет губой трясет - он на крестах сейчас.
В отличие от "во имя добра", в ней тебя проводят в первую очередь по абстракциям - посмотри содержание, как там список глав выглядит. После объяснения идут упражнения в конце каждой главы - в них ты обращаешься с этими абстракциями на практике. Это, как мне кажется, более здравый взгляд на основу языка, которой являются именно эти самые абстракции, а не способ написания hello world.
От "во имя добра" у меня осталось впечатление, что я могу воспроизвести примеры, которые там есть, и вроде понимаю, как они работают, но как только я пытаюсь сконструировать из данной мне инфы что-то сложнее этих примеров - не могу, сразу начинаются ошибки и появляются вопросы, ответы на которые в книге найти трудно. Может, я просто тупой, но сейчас я радуюсь Haskell Programming From First Principles и чувствую, что я не тупой, а просто нихуя не знаю, но могу узнать.
> Чем лучше "во имя добра"?
В воимядобра даже нет главы по монад трансформерам - одной из центральных фич.
Согласен с этим господином, даже нечего добавить.
Естественно, то что это вторая (или больше) книга по хачкилю, значения не имеет.
Ссылку на грамматическую норму?
Вот тебе цитата из учебника.
Если относительное слово относится ко всей главной части, а не отдельному её члену, то в главной части не может быть указательного слова, например: Мать очень беспокоилась об отце, что и во мне возбудило беспокойство.
Кроме того, указательное слово - в главном предложении, а не в придаточном.
Какая нахрен тян, есть же идеальный маскот - Гопник Хаскель - и придумывать ничего не надо.
https://ru.wikipedia.org/wiki/Гопник,_Хаскель_Моисеевич
Упражнение 1.14.
Нарисуйте дерево, иллюстрирующее процесс, который порождается процедурой count-change из раздела 1.2.2 при размене 11 центов. Каковы порядки роста памяти и числа шагов, используемых этим процессом при увеличении суммы, которую требуется разменять?
https://github.com/functional-experiments/sicp/blob/master/exercise_1.14.hs
Пикрилейтед из гугла, совпадает с ascii-art'ом из решения.
Логика в этом есть. type объявляет только тип, а data - все соответствующие структуры. Ну и у тебя даже на картинке написано: datatype declaration. Логично же?
>Хаскель Моисеевич Гопник
>Хаскель Гопник
>Моисеевич
Сука, он еще и хохол! Блядь, я не могу, в этом человеке идеально все.
Хаскель Гопник смотрит на тебя с интересом и некоторой иронией.
>> 1129320
Спасибо, попробую stack
Упражнение 1.15.
Синус угла (заданного в радианах) можно вычислить, если воспользоваться приближением sin x ≈ x при малых x и употребить тригонометрическое тождество (пикрилейтед) для уменьшения значения аргумента sin. (В этом упражнении мы будем считать, что угол «достаточно мал», если он не больше 0.1 радиана.) Эта идея используется в следующих процедурах:
(define (cube x) ( x x x))
(define (p x) (- ( 3 x) (* 4 (cube x))))
(define (sine angle)
(if (not (> (abs angle) 0.1))
angle
(p (sine (/ angle 3.0)))))
а. Сколько раз вызывается процедура p при вычислении (sine 12.15)?
б. Каковы порядки роста в терминах количества шагов и используемой памяти (как функция a)
для процесса, порождаемого процедурой sine при вычислении (sine a)?
https://github.com/functional-experiments/sicp/blob/master/exercise_1.15.hs
Для вопроса (а) добавил счетчик числа вызовов в саму функцию - со всеми ленивостями так просто логирование не добавить. Вообще этот момент - запрет на console.log() из нормальных функций - достаточно сильно мешает.
Для (б) - поленился считать, там какой-то неочевидный полином получался.
>запрет на console.log()
Тащем-то как раз в таких случаях можно использовать unsafePerformIO.
Упражнение 1.16.
Напишите процедуру, которая развивается в виде итеративного процесса и реализует возведение в степень за логарифмическое число шагов, как fast-expt. (Указание: используя наблюдение, что (bn/2 )2 = (b2 )n/2 , храните, помимо значения степени n и основания b, дополнительную переменную состояния a, и определите переход между состояниями так, чтобы произведение abn от шага к
шагу не менялось. Вначале значение a берется равным 1, а ответ получается как значение a в момент окончания процесса. В общем случае метод определения инварианта (invariant quantity), который не изменяется при переходе между шагами, является мощным способом размышления о построении итеративных алгоритмов.)
https://github.com/functional-experiments/sicp/blob/master/exercise_1.16.hs
Упражнение 1.17.
Алгоритмы возведения в степень из этого раздела основаны на повторяющемся умножении. Подоб-
ным же образом можно производить умножение с помощью повторяющегося сложения. Следующая
процедура умножения (в которой предполагается, что наш язык способен только складывать, но
не умножать) аналогична процедуре expt:
(define ( a b)
(if (= b 0)
0
(+ a ( a (- b 1)))))
Этот алгоритм затрачивает количество шагов, линейно пропорциональное b. Предположим теперь,
что, наряду со сложением, у нас есть операции double, которая удваивает целое число, и halve,
которая делит (четное) число на 2. Используя их, напишите процедуру, аналогичную fast-expt,
которая затрачивает логарифмическое число шагов.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.17.hs
Упражнение 1.18.
Используя результаты упражнений 1.16 и 1.17, разработайте процедуру, которая порождает итера-
тивный процесс для умножения двух чисел с помощью сложения, удвоения и деления пополам, и
затрачивает логарифмическое число шагов.
https://github.com/functional-experiments/sicp/blob/master/exercise_1.18.hs
А причем здесь Go?
Как успехи? Опять на работе интерпрайс разгребаешь?
Потому что reverse надо делать. Ну и элементы в списке и векторе добавляются с разных сторон, так что чисто визуально удобнее, если ты просто свою очередь просто как пару определишь.
>Потому что reverse надо делать
А как делать без reverse?
>элементы в списке и векторе добавляются с разных сторон
Это я не понял.
Я, конечно, встрял посреди беседы, но, видимо, здесь идёт речь про конструкцию списков.
Список может иметь только ДВА значения: [] или элемент : список. Т. е. список [1, 2, 3] - не что иное, как 1 : (2 : (3 :[])) (учитывая ассоциативность 1 : 2 : 3 : []). Соответственно, быстрее добавить элемент в начало, чем в конец. reverse же предлагается затем, чтобы хранить начало как конец, т. е. хранить список наоборот. Тогда добавление в конец будет являться, по сути, добавлением в начало. Потом превращаем это в список с помощью reverse. Вот, постарался объяснить.
Я, конечно, встрял посреди беседы, но, видимо, здесь идёт речь про конструкцию списков.
Список может иметь только ДВА значения: [] или элемент : список. Т. е. список [1, 2, 3] - не что иное, как 1 : (2 : (3 :[])) (учитывая ассоциативность 1 : 2 : 3 : []). Соответственно, быстрее добавить элемент в начало, чем в конец. reverse же предлагается затем, чтобы хранить начало как конец, т. е. хранить список наоборот. Тогда добавление в конец будет являться, по сути, добавлением в начало. Потом превращаем это в список с помощью reverse. Вот, постарался объяснить.
В чём профит хаскелля? Кроме оригинального (тм) мышления
И какая основная область применения?
людям он нравится за то что сам язык очень маленький и узконаправленный, без попытки объять необъятное и впихнуть невпихуемое. По сути он представляет один основной инструмент - функциональное программирование, который можно задрачивать до бесконечности, потому что инструмент позволяет изъёбываться через 4 пизды и восемь жоп. В то же время людям нравится что не надо отвлекаться на что то лишнее, так как в языке этого нет. Многим импанирует такой подход. Область применения, я думаю это просто игрушка для мозга, которая к тому же позволяет писать некоторые полезные тулзы в купе с чем либо еще, и дающее отдых уставшему от многообразия и лагающей еботни анону.
Могу сказать за типизированные функциональные языки в целом: их преимущество в том, что намного легче читать код и рассуждать о корректности, потому что программа напоминает последовательность вычислений как в математике. Это, например, актуально для конкаренси, потому что при написании конкурентного кода возникают хитровыебанные ошибки, которые очень тяжело найти и воспроизвести. Никакие индусские говнометодологии типа TDD, BDD и прочего не помогут, если говнокодить при написании конкаренси, единственный выход - писать нормальный код и доказывать его коррекность. Обычно это не формальное доказательство, а просто пристальное разглядывание кода и доказательство в уме. Но можно заморочиться и провести полностью формальное доказательство корректности того или иного участка кода, записать доказательство в каком-нибудь пруф асистанте типа Coq. Функциональные языки хороши тем, что доказывать корректность кода на них намного легче чем на императивных.
>Функциональные языки хороши тем, что доказывать корректность кода на них намного легче чем на императивных.
Дополню тебя: функциональные языки хороши тем, что писать корректный код на них намного легче чем на императивных.
Ну тут уже от задачи зависит. Например, когда нужно изменяемое состояние и сайд эффекты, то нихуя не проще. Обычные изменяемые переменные использовать проще чем монаду стэйт.
ST или STM, но никак не State. И свои сайд эффекты можешь просто в IO хуячить, никто не запрещает.
>изменяемое состояние
Что это? Дай вменяемое определение и поймёшь, что либо это не зависит от подхода ФП/не-ФП, либо не имеет смысла.
>сайд эффекты
А какие тут проблемы?
> изменяемое состояние
> что это
Это когда одно и то же выражение может дать разные результаты в зависимости от времени. Например, выражение, которое получает элемент из мутабельной структуры данных.
Алсо, функциональные структуры данных иногда намного менее очевидны в реализации, чем их императивные аналоги. Про них нужно отдельную книгу читать типа Криса Окасаки.
https://www.reddit.com/r/haskell/comments/8bofby/unplanned_hackage_downtime/ лол кек, ждем прохладную
Как то не уверен что она стоит покупки или даже пиратства.
Для начала пойми, монада - это такой моноид (множество с ассоциативной бинарной операцией и нейтралным элементом).
А что именно непонятно?
https://pastebin.com/raw/sFJUDJ3M
зачем там этот аккумулятор?? просто для аналогии с императивными?
или я чего-то не понимаю?
Вызов функции занимает место в стеке, аккумулятор позволяет не забивать его попусту.
Заменяется вредная рекурсия на безопасную хвостовую.
Прошу обоссывать.
>Simple, given a string of words, return the length of the shortest word(s).
>String will never be empty and you do not need to account for different data types.
module FindShortest where
find_shortest :: String -> Integer
find_shortest (x : xs) = fs_helper xs x 0 0
fs_helper :: [Char] -> Char -> Integer -> Integer -> Integer
fs_helper [] _ word_counter shortest
| shortest == 0 = (word_counter + 1)
| word_counter < shortest = (word_counter + 1)
| otherwise = shortest
fs_helper (argc2 : argstr) ' ' word_counter shortest
| shortest == 0 =
fs_helper argstr argc2 0 word_counter
| word_counter < shortest =
fs_helper argstr argc2 0 word_counter
| otherwise =
fs_helper argstr argc2 0 shortest
fs_helper (argc2 : argstr) _ word_counter shortest =
fs_helper argstr argc2 (word_counter + 1) shortest
Прошу обоссывать.
>Simple, given a string of words, return the length of the shortest word(s).
>String will never be empty and you do not need to account for different data types.
module FindShortest where
find_shortest :: String -> Integer
find_shortest (x : xs) = fs_helper xs x 0 0
fs_helper :: [Char] -> Char -> Integer -> Integer -> Integer
fs_helper [] _ word_counter shortest
| shortest == 0 = (word_counter + 1)
| word_counter < shortest = (word_counter + 1)
| otherwise = shortest
fs_helper (argc2 : argstr) ' ' word_counter shortest
| shortest == 0 =
fs_helper argstr argc2 0 word_counter
| word_counter < shortest =
fs_helper argstr argc2 0 word_counter
| otherwise =
fs_helper argstr argc2 0 shortest
fs_helper (argc2 : argstr) _ word_counter shortest =
fs_helper argstr argc2 (word_counter + 1) shortest
Не разбирал простыню кода, но вот к чему ты должен стремиться:
shortest :: String -> Int
shortest = minimum . fmap length . words
Разделять идентификаторы в хуцкеле подчеркиванием - это моветон, как по мне. Именования переменных вообще пиздец.
Удваиваю. Этот хаскеллист кое-что смыслит.
>Разделять идентификаторы в хуцкеле подчеркиванием
Не виноватая я, так на сайте было.
>Именования переменных
А как надо?
Где можно почитать список функций типа words, length?
> А как надо?
Если пишешь код и потом им себе анус щекочешь, то как угодно. Если выставляешь на обозрение одному человеку и более, то, как минимум, осмысленнее и при этом как можно короче без потери смысловой нагрузки, а не argxyi7/argstr1/best_wrod_counter_in_the_world. Если один/два параметра у функции, зачастую просто x, y или первые буквы полного имени, так как при чтении такой функции не сложно держать в голове информацию о них.
Но это всего лишь придирки, ведь самый пиздец в том, что ты задание не так понял, функция выполняет не то, что нужно.
>Где можно почитать список функций типа words, length?
google: haskell prelude
google: haskell basic libraries
Советую начать учить хуцкель с пикрила. Чтиво не из легких, но зато минимум воды, прям от корки до корки ебашь.
>Но это всего лишь придирки, ведь самый пиздец в том, что ты задание не так понял, функция выполняет не то, что нужно.
Да ты чо, а чо у меня система приняла?
>Чтиво не из легких, но зато минимум воды, прям от корки до корки ебашь.
Там тыща страниц, это там-то нет воды?
А так нормально, её и читаю.
> у меня система приняла
Да, я обосрался. Уверен был, что
> = (word_counter + 1)
возвращает позицию наименьшего слова, исходя из названия. letter_counter тогда уж, лол.
Слышал, что математики любят функциональное программирование, которое к тому же помогает параллелить, ибо устраняет зависимости между данными.
Тащем-то производительные числодробилки подразумевают байтоебство. А если тебе именно в плане покодить то, что изучаешь - да, самое то.
Это работает: https://ideone.com/ADh9bm
А тут нет: https://ideone.com/9Q3bDr
>числодробление
Тут два пути.
1) По хардкору используешь FORTRAN, пишешь всё сам
2) По хардкору используешь всякие BLAS и LAPACK, которые сами были написаны в фортране, но через обёртки в плюсах или питоне.
Типы и в питоне не всегда тип `type` имеют. Это стандартный метакласс, и его можно переопределить.
Проблема тут в том что у `type` самого тип `type` и возникает порочный круг, который мешает каким-то хорошим свойствам теории типов.
Поэтому в Haskell типы-типов называются `kind` и у они все что обычные типы умеют. Подробности гугли, я не очень разбираюсь в вопросе. Полноценные бесконечные иерархии типов есть в языках с зависимыми типами, типа Coq и Idris.
Пример:
```
Prelude> :k Int
Int :: *
```
Ну а хули ты хотел? У тебя тип a должен стать неким m b. Откуда компилятору знать что ты там имел ввиду под b?
Вот тебе более простой аналогичный случай:
main = print $ read "5"
Prelude Data.Scientific> x / 7
^CInterrupted.
Prelude Data.Scientific> (x / 7) 7
^CInterrupted.
Prelude Data.Scientific> x 7 / 7
1.0
Че делать? Расходимость так и прёт.
Монада - это моноид из категории эндофункторов.
Вернись в /по/рашу.
Монада M это тайп констрактор. Берёшь M, тип a, и получаешь тип M a, у которого есть байнд (>>= :: M a -> (a -> M b) -> M b), ретёрн (return :: a -> M a) и который подчиняется паре простых законов. Всё остальное лишь свистоперделки, которые можно получить из этих двух функций.
Вообще >>188221 годную вещь указал, почитай: https://fsharpforfunandprofit.com/rop/
Какой-то хуёвый пример, с read всё понятно, его реализации имеют кучи типов. Во что парсить строку он не может понять.
Однако тут компилятор не может воткнуть, какой тип monadConcat возвращается при известном типе аргумента.
Хотя функция для этого типа аргумента всегда ОДНА, так как типы ([Int] и [[[int]]]) имплементирует по одной монаде, тут не может быть никакой двоякости.
Никакой другой тип результата невозможен для данного аргумента, поэтому описание типа результата избыточно, однако компилятор тупит.
Если туплю я, то какой тип кроме [Int] подойдёт для result1/result2?
Для лучшего примера. https://ideone.com/8P3ETU
>У тебя тип a должен стать неким m b. Откуда компилятору знать что ты там имел ввиду под b?
Вот смотри, есть 2 варианта реализации monadConcat:
1) a ~ b. Должен срабатывать, если у меня входной аргумент не вложенный список ([[]]). Из этого кейса тип результат вычисляется, как тип аргумента.
2) Если же входной аргумент вложенный список, то рекурсивно проверяем тип результата повторным вызовом monadConcat, до тех пор, пока не придём к пункту 1.
Вот нахуй тут подсказывать компилятору тип результата?
>1) a ~ b. Должен срабатывать, если у меня входной аргумент не вложенный список ([[]]). Из этого кейса тип результат вычисляется, как тип аргумента.
Нихуя. Нет ограничения на то, что a не может быть вложенным списком. Так что, a может быть чем угодно. И вложенным списком, и хуем в пизде. Из-за этого и неоднозначность.
>Нихуя. Нет ограничения на то, что a не может быть вложенным списком. Так что, a может быть чем угодно. И вложенным списком, и хуем в пизде. Из-за этого и неоднозначность.
Если это вложенный список, то должен обрабатываться "instance (Monad m, MonadConcat m (m a) b) => MonadConcat m (m (m a)) b".
Это же блядь по сути паттерн-матчинг, только для системы типов. Все 100% кейсов логически раскладываются в 2 инстанса. Схуяли так тупо то?
>Нет ограничения на то, что a не может быть вложенным списком.
Ну ок, компилятору можно подсказать, что ЭТО НЕ МОЖЕТ БЫТЬ вложенной монадой? Т.е. по сути нужно логическое отрицание "MonadConcat m (m a) b".
sum' [x] = x
sum' (x:xs) = x + sum' xs
Без sum' :: [Int] -> Int выдает нон еххаустиве паттернс
С определением работает
Попробуй вызвать свою функцию от пустого списка и поймёшь в чём суть.
Используй моноид Sum и не епи себе моск.
https://hh.ru/vacancy/26915246
Я точно не знаю, но думаю, что идея в следующем.
Haskell старается соблюдать принцип того, что добавление новых деклараций не должно ломать старый код. А в данном случае, если ты добавишь новых инстансов, то однозначность нахождения реалиции нарушится.
Подскажи, пожалуйста, как называется паттерн, суть которого состоит в последовательном применении такий функций, как map, filter, reduce. Напрочь вылетело из головы.
Stream API из джавы так же является реализацией данного паттерна.
Это паттерн Вызов функций. Ну у тебя есть функция, и ты ее вызываешь. А если хочешь вызвать сразу несколько, то используешь композицию. паттерн блять, лол
Откуда это желание усложнять? Какой нахуй паттерн?
Т Р А Н С Д Ь Ю С Е Р Ы
а по делу, этот >>239429 прав
но есть (в том числе в хаскеле) довольно много реализаций апи над коллекциями\стримами\етк
помимо трандьюсеров, есть еще обычные итераторы\сиквенсы, есть iteratee, есть линзы (для вложенных конечных коллекций), сюда же можно зипперы по идее добавить, ну и еще куча всего чего я не знаю, можешь посмотреть разные prelude в сабже
Объясни зачем нужны трансдьюсеры, чем они отличаются от ленивых вычислений которые уже из коробки в Хаскеле? Давно пытаюсь это понять, может ты сможешь помочь?
Трансдьюсеры к ленивости вообще не имеют отношения. Это чисто функциональные трансформации, которые ничего не знают о том, как получившиеся функции будут выполняться - лениво ли, энергично ли, над коллекциями или вообще над чем-то другим. То есть трансдьюсер просто берет одну функцию, которую можно скормить в fold, и возвращает другую. Там есть еще кое-какие детали, но в целом идея думаю понятна.
В кложе по умолчанию как раз используются ленивые коллекции (как в хаскеле, только ленивость не на уровне всего языка, а именно на уровне коллекций), а трансдьюсеры к коллекциям не привязаны - их можно, например, накинуть на асинхронные каналы в го-блоках.
>Там есть еще кое-какие детали, но в целом идея думаю понятна.
Нет, совсем не понятна. Я могу скормить в fold функцию (+1). И могу (*2). Теперь я просто беру и объединяю их композицией (+1).(2) Зачем мне нужен какой то трансдьюсер?
Не можешь, почитай, что такое fold (можешь "tutorial on unversality and expressiveness of fold" навернуть).
Ну и трансдьюсеры композируются и так обычной композицией, лол. А вот reducing functions ты обычной композицией не скомпозируешь, потому что, ну, и типы не совпадут, и есть всякие нюансы типа раннего выхода (ищем элемент, нашли - зачем дальше кушать инпут? выходим), внутреннего локального состояния и т.п.
Лол, и правда ведь. Кажется я начинаю понемногу прозревать. Мне казалось это как раз с map связано все.
>>239699
>То есть трансдьюсер просто берет одну функцию, которую можно скормить в fold, и возвращает другую.
И какую он функцию тогда возвращает. Если я допустим скормлю (+).
Как тогда трансдьюсеры композируются?
А можно примеры на Хаскеле, только попроще?
Да, трансдьюсеры, хотел их упомянуть. Но мне казалось, что я пытался вспомнить какое-то другое слово
Короче глянь пикрелейтед (rf = reducing function, conj = добавление элемента в список), лень сейчас на х-ле переписывать
Обожжи
(empty xs)
Это предикат возвращающий true на пустом списке (почему тогда без ?) или просто пустой список (но зачем тогда нужен аргумент не понятно)
Возвращает пустую коллекцию того же типа, что и переданный аргумент. Ну это вообще там необязательно, можешь мысленно заменить на [].
Блядь, ну прочитай еще раз, что тебе пишут. map и filter работают с коллекциями. Трансдьюсеры не работают с коллекциями и ничего о них не знают (смотри код). Можно построить цепочку трансформаций, аналогичую map (+1) . filter even, и она ничего не будет знать и никак не будет зависеть от конкретных коллекций. Можешь потом ее применить к итераторам, ленивым спискам, векторам, асинхронным каналам, еще каким-нибудь хитровыебанным абстракциям - твои map и filter уже будут с ними работать (и притом эффективно) без дополнительного кода. Посмотри определение map в prelude. Потом посмотри определение mapping у меня на пике. Уловил?
>>240106
[] - это вектора (иммутабельные массивы, amortized constant time операции доступа по индексу), а не говносписки. "Пиздец-пиздец" - это как раз списки по умолчанию для всех sequential вещей, привет 80-ые. Как раз поэтому кстати эликсир сосет и никто в здравом уме не пользуется prelude функциями для чего-то кроме хелло ворлдов и факториалов.
А можешь мне их типы расписать и алгебры этих самых трансдьюсеров? Может вот тогда то я докумекаю.
Ну тебе ведь написали уже (упрощенные) типы. Полные типы по смыслу будут такими же, только все надо обернуть в десять манаток и тайпклассов, чтобы заиметь локалстейт\ранний выход и 0,1,2-арные операторы. Короче, let me google that for you, блядь: https://conscientiousprogrammer.com/blog/2014/08/07/understanding-cloure-transducers-through-types/
То есть у тебя лёгкий случай байтоёбства - процедурное программирование головного мозга и ты не можешь в пуризм, всё понятно.
Профит чистой функциональщины (как в хаскеле) в упрощении доказательств. Для промышленного кода это не всегда удобно, да, и обычная функциональщина (окамл, кложа, скала, эликсир) обычно тупо удобнее.
Алсо, я не уверен, что правильно тебя понял, но ты ведь понимаешь, что жс и перл - это не особо функциональные языки, потому что в них нет человеческой модели состояния? Типы данных там по умолчанию изменяемые, поэтому ты программируешь с байтами и структурами вместо списков и мапов.
традиции-двача.пнг
Кто там про трансдьюсеры спрашивал?
Вот вам объяснение с морфизмами и котегориями:
https://nextjournal.com/zampino/fold
Охуенная кстати штука этот некстжоурнал
Блин, все это хорошо, но если бы я любил скобочки и динамическую дрисню, я бы тогда заглядывал совсем в другой тред.
Сейчас что то нет сил разбираться с этими вашими дрансдьюсерами. Если бы кто мне максимально доступно объяснил - вот у меня есть такая-такая проблема, и я применяю трансдьюсер и заебок. С примерами на хачкеле только; хачкель - сила, скобки - могила.
Почему в шапке нет Душкина, я не понял?
Нельзя интересоваться временем.
Ни в одном более-менее сложном языке нет. Хаскель тут мало чем отличается от тех же крестов, например.
> foo(a)
> догадайся, сколько функция займёт, без её определения
>>250466
> крестов
Ну если тебе кресты непонятны, то тебе и С непонятен, потому что рантайм практически тот же.
Для тебя компилятор предоставляет возможность самостоятельно плеваться функциями, если ты дашь ему шаблон, инкапсулировать функции в структурах, называя это классами.
По сути, конструкторы, деструкторы - вызовы С-функций, автоматические.
Ну вот фича с виртуальными функциями и сворачиванием стека - это, конечно, новизна. Но это тоже не далёкий скачок от С.
А рантайм С это то, на чём все учат студентов, алгоритмам там, ну или просто структурам данных, это то, что программисты, как они считают, понимают глубоко и с нюансами.
Я не знаю Хаскелль ваш пока что, но разве он не продолжает многие идеи Лиспа и его Лисп-машин?
>Я не знаю Хаскелль ваш пока что, но разве он не продолжает многие идеи Лиспа и его Лисп-машин?
Я сам мимокрокодил, но хаскель вроде как идейный потомок ML-семейства, это немного другая ветвь эволюции языков.
Ну да, по сути вся скорость работы сводится не к естественности и нативности языка для машины, а к миллионам человеко-часов пыхтения над компилятором.
>Ну да, по сути вся скорость работы сводится не к естественности и нативности языка ассемблера и машинных кодов для машины, а к миллионам человеко-часов пыхтения над дырявыми приборчиками в процессорах, чтобы потом Spectre, Meltdown, TLBleed.
Не понимаю, о чём он, но, короче, данные грузятся в кеш целыми линиями, т.е. тебе надо сделать так, чтобы загружались сразу только нужные, и как можно меньше ненужных, чтобы не лазить в ОЗУ лишний раз, и чтобы кеш всегда был актуален. В линию, погружаются, очевидно, подряд идущие данные. Так что массивы тоже могут приемлемы при соблюдённых правилах.
В контексте многопокпока об этом написано у Энтони Уильямс в "Практике разработки многопоточных программ". Но там речь о перебрасывании кеша в основном.
Но суть будет доведена.
Так и должно быть. Один раз написать хороший оптимизирующий компилятор полезнее, чем каждый раз писать оптимизированную под одну архитектуру программу.
>2018
>До сих пор нет нормальной интеграции с редакторами
А ведь я всего-то хочу видеть удобное отображение результатов QuickCheck-тестов.
Во-первых, это всего лишь иллюстрация, и я слегка удивлен, что ты ее не понял.
Во-вторых, лучше быть жс-петушком, чем токсичным мудаком.
> ошибки в коментах
Вот это дебил.
Никто так не делает, кроме ЖСтуна.
Это только ЖС-дебилам так можно, а так - проваливай.
>implying что это настоящие комменты
Ты действительно не понимаешь, что это просто визуализация, которая исчезнет как только ошибка будет исправлена?
>проваливай
Нет ты! Токсичные педики должны уйти.
>>251624
Имакс всем хорош, кроме кривой обучения. Не стану я использовать инструменты, которые даже потенциально не смогу подсунуть коллегам.
>>251627
Да знаю я где нахожусь, знаю. Но не обязательно же вести себя так.
Держи леденец, няша.
> это просто визуализация
Ты настолько туп, что не понимаешь, что шрифты твоих исходников это просто визуализация, и они исчезнут, если ты застрелишься
>Имакс всем хорош, кроме кривой обучения.
Согласен. Спейсмакс помогает, но не до конца.
>Не стану я использовать инструменты, которые даже потенциально не смогу подсунуть коллегам.
Я не Ъ-хаскеллист, так что вообще не в курсе, что там сейчас в основном используется. Но когда ковырял его некоторое время назад, имакс вроде был единственной нормальной IDE (и вроде бы ничего особо не поменялось). Если тебе нужно потенциально сажать коллег, то одним стулом всегда следует предлагать простой терминал-бейзед воркфлоу с перезагрузкой тестов при изменении файлов на диске и возможностью использовать любой редактор.
Еще можешь на ризон глянуть, там плугин для атома активно пилится фейсбуком, ну и в целом продать его (может быть) проще.
>>251620
>>251634
Съеби обратно в ньюфаг-тред, пожалуйста.
VS Code + Haskell Language Server
Ого, действительно годнота!
HTTP очень хорошо пишется, если использовать Servant.
pandoc, например - швейцарский нож для текстовых форматов
или shellcheck, например
это из того, чем повседневно пользуюсь
Двачую xmonad, довольно долго им пользовался, но переехал году в 13 на awesome а потом на i3wm из-за того, что у него интеграция с панелькой была какая-то невразумительная. Есть кто-нибудь, кто его юзает? Как там сейчас, polybar смогу прикрутить?
Понимаю, что это не /s/, но у вас один хрен тред полумёртвый
>Как при социализме реализуется поощрение работников общественно важных профессий, ведь давать им премии и делать зарплату больше нельзя
Меняют значения.
> Через деревья
У хэша сложность в среднем лучше, и при правильном подходе он компактнее. Так что это не замена.
Насколько я понял, существующие реализации хэшей работают через unsafe код, и единственный разумный способ использования - сначала разом весь построить, потом только чтение. Иначе тебе нужно дерево, т. к. чистота
>У хэша сложность в среднем лучше
Чем у чего? Чем у хэша?
>Так что это не замена.
А мужики-то и не знали...
>Насколько я понял
Нихуя ты не понял, тебе все ссылки еще в том треде вкинули. Меньше выебывайся и больше читай.
> Чем у чего? Чем у хэша?
Чем у дерева, очевидно. У хэша в среднем O(n), у дерева - O(n log n)
> А мужики-то и не знали...
Не замена в том смысле, что во многих случаях честная хэш-таблица будет быстрее. Так-то понятно, что всё это маппинг
> >Насколько я понял
> Нихуя ты не понял, тебе все ссылки еще в том треде вкинули. Меньше выебывайся и больше читай.
Я правда не понял, но ссылки ты давал кому-то другому, это был мой первый пост на этой доске. Посмотрел - хэши реализуются в монадах IO и ST (ожидаемо). Хак с unsafePerformIO я видимо где-то в другом месте видел
Алсо, у меня как (только не бейте ногами) хорошо знакомого с лиспом вызывают уныние вот такие простыни копипасты как здесь:
http://hackage.haskell.org/package/hashtables-1.2.3.1/docs/src/Data-HashTable-IO.html#insert
На лиспе бы просто написали макрос, который бы нагенерил всех этих обёрток вместе с декларациями. Неужели в хаскеле до сих пор нет ничего, что позволит обойтись без копипасты? Смотрел на template haskell, но он, насколько я понял, не может в декларации (вот эти SPECIALIZE и пр), да и не выглядит сильно удобным.
>Чем у дерева, очевидно.
У хэшмапа сложность лучше, чем у хэшмапа, я тебя услышал. Я нихуя не понимаю, что ты имеешь в виду и о какой сложности ты говоришь. Доступ у хэшмапов на деревьях - log_a n для большого a, effective constant time который.
>во многих случаях честная хэш-таблица будет быстрее.
Ну так и код на си во многих случаях будет быстрее кода на питоне. Это же не повод говорить, что пайтон - не замена си для написания сайтиков, например. Узкое место у тебя будет, только если ты заполняешь за один раз огромный хэш с нуля, но ровно для таких случаев и существуют транзиенты. Как впихнуть транзиенты в чистый язык - это уже другой вопросhttps://github.com/ekmett/transients
>Я правда не понял, но ссылки ты давал кому-то другому, это был мой первый пост на этой доске.
Ну ладно, извини тогда, анон.
>только не бейте ногами
Лол, да я как бы тоже не хаскеллист, бггг.
>но он, насколько я понял, не может в декларации
Хм, нет, я погуглил и получается, что он все-таки может в прагмы.
>да и не выглядит сильно удобным.
Ящитаю в негомоиконном (тем более статически-типизированном) языке удобных макросов в принципе быть не может.
Виталя, неужели ты на двощах сидишь?
>Ну так и код на си во многих случаях будет быстрее кода на питоне.
Он будет быстрее только в рамках Tilde Notation, Big Oh таким же будет.
>Скорость != сложность.
А если программа под большой нагрузкой работает? Или производит сложные вычисления?
То скорость все еще != вычислительная сложность, очевидно, так как это по определению понятия разных категорий. Я не улавливаю, о чем вообще разговор сейчас идет?
>скорость все еще != вычислительная сложность
Но ведь вычислительная сложность напрямую определяет скорость. Ты какой-то сектант, вбил себе в бестолковку, что хэш-таблицы и деревья это одно и тоже и прикидываешься тут дурачком.
>Но ведь вычислительная сложность напрямую определяет скорость.
Нет, не напрямую. Если ты на практике не встречался со случаями, когда алгоритм с лучшей сложностью дает худшую скорость, то можешь хотя бы просто погуглить материалы про асимптотический анализ алгоритмов - в любой вводной статье это описывается.
>что хэш-таблицы и деревья это одно и тоже
Почитай в гугле, что такое хэшмапы, и осознай, что хэшмапы могут быть мутабельными или иммутабельными, и что иммутабельные хэшмапы могут быть реализованы с помощью деревьев. Я уже в трех постах тебе на это указывал.
Вместо того, чтобы кидаться пустыми оскорблениями, разберись с понятиями, которые используешь. Это как минимум интереснее, согласись.
>когда алгоритм с лучшей сложностью дает худшую скорость
Там либо константы при N большие, либо объем данных небольшой, но тогда про асимптоты речи не должно идти.
>могут быть реализованы с помощью деревьев
А я и не спорил, что не могут. Только как O(1) получить?
>Только как O(1) получить?
Я уже писал по этому поводу в >>256577-посте под спойлером. Ъ-O(1) не будет впрочем, его и для мутабельных хэшмапов тоже не будет, строго говоря, будет логарифм_32 или что-то в таком роде, что называется amortized\effective constant time - то есть на реальных данных, которые в хэшмапу могут поместиться, она ведет себя почти как O(1), но на самом деле там просто очень пологий рост.
Ъ-O(1) на самом деле не Ъ, а такой же, как у мутабельных хэшмапов можно получить через линейные типы а-ля Раст, когда ты на самом деле свою хэшмапу ебешь и в хвост и в гриву меняешь, но компилятор может доказать, что эти изменения никогда не видны извне имплементации, а потому эффективно она является иммутабельной. Но так ты теряешь персистентность и к тому же это никому ненужно, так как на практике разницы между 1 и лог32 нет.
Вообще, на практике важно не столько это, сколько потребление памяти например, иммутабельные мапы шринкаются (отдают мусор гц) автоматически при удалении элементов, а мутабельные продолжают занимать максимально достигнутый объем; в каких-то случаях это хорошо, в каких-то - плохо, дружба с многопоточностью иммутабельные структуры, очевидно, автоматически безопасны при доступе из нескольких потоков, паттерны доступа например, при конкурентном обновлении больших вложенных хэшмапов возникают случаи, когда у тебя два разных потока идут в разные "поддеревья" твоих хэшмапов (то есть операции коммутативны), но со стандартными структурами ты их будешь зря лочить\перезапускать транзакцию, поэтому оптимальнее использовать особую, уличную хэшмапу, которая понимает вложенность и независимость путей и т.п.
>>256718
Да без проблем. Но с понятиями все равно разберись :P
>Ъ-O(1) не будет
Ну почему же, если хеш нормально считается, то коллизий не будет, либо их количество будет минимальным. Можно двойное хеширование использовать, тогда коллизий практически не будет. Плюс, если известен объем данных, то можно создать хеш-таблицу сразу нужного размера.
К тому же, у деревьев есть еще пара проблем: больше потребление памяти и промахи в кэше процессора.
>на практике разницы между 1 и лог32 нет
Я бы не сказал, в критичных по скорости участках она вполне может быть. Но для 99% приложений да, скорее похуй.
>Ну почему же
Ну потому что все известные мне реализации хэшмапов подразумевают возможность коллизий. Если это считать "Ъ-O(1)", то и у дерева такой же "Ъ-O(1)".
>больше потребление памяти
Про память я уже написал, что оно может быть как больше, так и меньше, зависит от данных.
>промахи в кэше процессора.
А с мутабельной хэшмапой в какой-нибудь джаве промахи в кэше магически исчезнут? Кулстори, бро.
>>256766
Да, согласен. Под "на практике" я это и имел в виду.
>>256767
Ну там же не бинарные, а очень широкие деревья используются, 32-арные например.
Спасибо
в GHC
Добавьте уже в шапку конфу треда, там все два с половиной анона сидят @hcdev
Это все-таки зашугаренное пердоленье с обычными Чарами?
Или как оно работает на низком уровне?
Объясните, плизки
Вкатился в тред и сразу наткнулся на
> https://github.com/jystic/hadoop-tools/tree/master/hadoop-tools
Почему там один файл на 500 строк кода? В хаскеле нельзя модульно все делать? Тогда я выкатываюсь.
В глаза ебешься?
Чем это раст безопаснее хаскеля?
В расте не устраивает вот что:
1, Ебать как долго компилится
2. Молодая экосистема, некоторых либ либо вообще нет, либо они кривые и хуевые
3. В тех либах что есть, видно что протекает раби-сознание авторов это я про актикс, когда выполнение зависит от какого-то глобального состояния, и валится с паникой в рантайме.
Про котлин вообще говорить нечего, это просто ебаное легаси от которого потихоньку избавляемся.
Мне в целом раст нравится, а за хачкель топит коллега-наркоман.
У нас есть гуру хаскеля, я сам более менее знаю. Так что это не проблема вкатывания.
>Про котлин вообще говорить нечего, это просто ебаное легаси от которого потихоньку избавляемся.
Я аж смуззи поперхнулся от этого.
Стек меняете каждые три месяца?
Узнал всё от "node.js"-бога. Такие дела.
Есть вообще кто-то тупее js-макак в принципе?
пхп-макаки?
Офигеть, где-то хаскель собираются использовать в промышленном коде. А что за компания или хотя бы область деятельности, если боишься дианона? Не боитесь, что потом нового хаскелиста будете три года искать когда ваш гуру из запоя не вернётся?
Я без наезда, просто вот этот аргумент (сложный найм)обычно первым приводят когда предлагаешь редкий язык.
Стартап в финансовом секторе. Более того, у нас тут страна с населением в 5 миллионов человек. Так что скорее всего хаскель тут знает как раз наш наркоман и еще 2 человека.
>Чем это раст безопаснее хаскеля?
От ленивости пиздюлей не огребешь. Понятней, предсказуемей. Ну ебли побольше, да.
Три пункта жизненные, тут спору нет.
>>262114
В окамле синтаксис слегка уебанский местами, вместо встроенной стандартной библиотеки сторонняя (но впрочем от того не менее стандартная), нет ленивости, можно в мутабельность без ебли с манатками, можно компилять в жс, есть конкурентность, нет параллелизма, людей в целом наверное поменьше, чем у х-ля... хуй знает, если у вас есть гуру, то логичнее взять то, в чем он шарит.
>>262388
>Стартап в финансовом секторе.
Бля, ну тогда сам бох велел х-ль брать! или окамл
>>262383
Да ну на удаленку-то не проблема будет голодного сиэс-мейджора найти
>Офигеть, где-то хаскель собираются использовать в промышленном коде
https://github.com/erkmos/haskell-companies
>>262604
>От ленивости пиздюлей не огребешь.
сказки о проблемах с ленивостью расказывают довны ничего на хаскеле не написавшие
>можно в мутабельность без ебли с манатками
как что-то хорошее
>можно компилять в жс
как и хаскель
>>262605
this
>Сказки о проблемах с указателями в С рассказывают довны, если ты выстрелил себе в колено -- то проблема в тебе, а не в дробовике
>Сказки о проблемах с указателями в С рассказывают довны, если ты выстрелил себе в колено -- то проблема в тебе, а не в дробовике
Именно так, дебич.
Наличие windows и linux (написаны на C) и отсутствие других операционных систем, которые не ноунейм (написанных на бизопасной абстрактопитушне) - этот факт подтверждает.
Проблема не в написании ОС, а в том что никто под твою ос не будет переписывать софт. А если ты эмулируешь линакс, то нахуй ты нужен?
>Над чем ржать то?
>go
>кококобизопасно сборщик мусора
>скриншоты как наша кококобизопасная OS выглядит
>kernel panic : system halted
ОС со сборщиком мусора? Смишно.
Но судя по остальным скринам оно паникует вполне логично, потому что init обосрался по причине отсутствия оного.
>сказки о проблемах с ленивостью расказывают
Тебе уже ответили, поддвачну того анона.
>как что-то хорошее
Да.
>как и хаскель
Разве там есть что-то живое? ghcjs, или про что ты?
>this
Спасибо.
ПОСТАВИЛ -1 ВМЕСТО (-1)
@
В ФУНКЦИЮ ПЕРЕДАНО НА ОДИН ПАРАМЕТР МЕНЬШЕ
@
ОХУЕВАЕШЬ ОТ НЕЧИТАЕМЫХ ОШИБОК
@
КОММЕНТИШЬ ПО ОДНОЙ ФУНКЦИИ, ЧТОБЫ ЛОКАЛИЗИРОВАТЬ ОШИБКУ
В хачкеле для написания кода тебе надо искать экстремумы, локальные минимум и максимумы, доказывать теоремы, брать производные и интегралы, находить пределы функций? Что ты несёшь блядь. Есть подоплёка аппликативов, монад, функторов теории категорий к математическим моделям, только тебе для дрочбы в хачкеел со всем этим не надо об этом задумываться.
трустори, вчера делал задачу из курса на степике и минут 5 охуевал с простейшей ошибки. Сообщения от компилятора еще хуже, чем от матерого шаблонного кода в C++. В хаскелле даже имена функций не пишутся. Иди ебись, сравнивая типы, что называется. Очень удобнонет
>вчера делал задачу из курса на степике
Ну скинь код с ошибкой и сообщение тогда, чтобы не быть голословным, давай всем тредом попробуем угадать.
Что надо устанавливать, какую IDE-шку использовать? На оф сайте какие-то 3 разных варианта установки, в вики ещё пять. Что наиболее православно? У меня мак.
По книжкам вроде вот эту рекомендуют?
https://www.amazon.com/Haskell-School-Expression-Functional-Programming/dp/0521644089
> emacs + intero
братишка спасибо за совет, я не сомневаюсь в чистоте намерений, но боюсь emacs слишком хардкорно для меня :3
Что-нибудь бы типа vsсode или на худой конец от JetBrains..
Книжку заценю, спасибо.
Например. Делается каррирование и из функции с одним параметром вычитается 1. Как это можно понять из сообщения от компилятора?
Алсо буду признателен, если кто-то объяснит этот мунспик: a :: forall a. (Num (a -> a), Num a) => a -> a
>но боюсь emacs слишком хардкорно для меня :3
Spacemacs попробуй, это вариация емакса для домохозяек с vi-шными кейбиндингами. dw знаешь? ну вот оно
Да пиши для начала в любой онлайн идешке. Потом просто поставь ghc любым способом, ghci в терминале запусти. Потом уже со stack разберешься. Но спейсмакс двачну.
>a :: forall a. (Num (a -> a), Num a) => a -> a
Это еще что, ты попробуй test -1 2 3 запустить.
А все почему? Безблагодатность обколются своим синтаксическим сахаром и ябут друг друга в парсеры. Нет бы как диды завещали делать, родина дала им sexpr'ы - нет, не хочу, хочу в парсеры ебаться и отлавливать баги с -1 и (-1). Зато статическая типизация. Мудачье, блядь, пидоры. И это программисты? Синтаксиса нацепили, говно жрут - пидоры, блядь, ебаные...
# test 1 2 -1;;
Error: This expression has type int -> int
but an expression was expected of type int
но по большому счету тоже говно безблагодатное, конечно
> (define (test a b c) (+ a b c))
> (test 1 2 -1)
2
Слышишь, как ангелы тихонько поют, когда ты читаешь этот код?
Как дела вообще с трудоустройством, полный пиздец? Что по деньгам?
так 2ch.hk — это же halls of elita
Но вообще, если серьёзно, а хули нет. Вполне возможно, что все 2 российских хаскеллиста тут сидят.
Да не. Иди в жж к мише хаскеллистов ловить.
О, заодно вспомнил, ещё один элегантный, бесподобный термин, когда ботал химию. Внимание, маэстро в треде! Как вам такое -- "Гетерогенный список содержащий гомогенные списки разной структуры". Красиво? Вот это да, меня самого распирает от своей мудрости. Вот это я илитарий, БЛЯ. Прямо чувствую себя нитакимкаквсе долбаёбом
Я конечно уже понял, что в хаскеле лист гомогенный и он не может быть гетерогенным(так ведь?) но слушайте, это же охуенно звучит.
Прости меня грешного
Ну во. Дошёл до кортежей. Они как раз не гомогенные, а гетерогенные. То что я и хотел получить от списка есть в кортежах.
Кстати, вот что-то на тему гетерогенных списков, но я даже не разбирался, что там да как.
https://wiki.haskell.org/Fully-functional_heterogeneous_lists
Рекорды и кортежи едины в своей сути. Следуй свету знаний, но не дай бесам сбить тебя с истинного пути.
мимоумудренный старец
Почему ты список называешь "рекордами"? Я что-то не понимаю или это опечатка? Они похожи(как и все структуры данных), но у них есть несколько фундаментальных различий.
Я не дам бесам сбить меня с истинного пути, это же обычная любознательность.
Ааа... лол, я всё понял. Я двусмысленно понял слово "рекорд". Погуглил - теперь всё понял. Извиняюсь за такой глупый вопрос тогда.
Говорят, когда компилятор GHC запускают с параметром UndecidableInstances, он спрашивает ответ лично у Олега, поэтому и работает.
>поделитесь опытом, насколько потом стабильна и предсказуема скорость исполнения
Скорость скорость исполнения абсолютно нестабильна и совершенно непредсказуема. Впрочем, как и у любой достаточно сложной программы, написанной на eager языке.
>что у Хаскеля с профилированием?
Профилирование охуенное. Аналоги criterion выглядят как быдлокодерские поделки (которыми они и являются). Впрочем, даже такие тулзы как criterion тебе не особо помогут в профилировании сложной программы.
Ты, блядь, как студент, который hello world написал. Типа "возьму я Си, там же я всё контролирую, я напишу самую быструю программу, а все остальные соснут!" Но нет, нихуя, сложность программы константна, и если ты возьмёшь lazy язык, или eager язык, ты одинаково заебёшься, просто в разных местах. И HPC на Хаскелле - это такое же байтоёбство, как на Cи. Хочешь выжимать максимум из программы, будь добр понимать, как работает компилятор и процессор, и руками под них всё оптимизировать. Это работает и для Хаскеля и для Джавы и для С++ абсолютно одинаково, и между eager и lazy нет особой разницы.
Ты вы целом адекватен, братишка. Поэтому я поясню, что я как раз не студент и вполне себе занимаюсь байтоёбством и оптимизацией ебучих микросекунд. Читаю сейчас про Хаскель для саморазвития, и вот как-то возник выше обозначенный вопрос, сам понимаешь что если С относительно прозрачно разворачивается в Асм, плюс минус вполне описанные и предсказуемые оптимизации, то рантайм Хаскеля со стороны (я нуб в этой конкретной теме) выглядит как черный ящик с ебучей магией внутри.
Потому и любопытно, насколько это ящик бел, чист и ясен для тех, кто в теме
Это Ева Грин?
можешь пердолить байты вручную сколько хочешь http://hackage.haskell.org/package/ghc-prim-0.5.3/docs/GHC-Prim.html
> то рантайм Хаскеля со стороны (я нуб в этой конкретной теме) выглядит как черный ящик с ебучей магией внутри.
LLVM для хачкеля давно написан
Вот нахуй я сюда зашёл? Ты мне настроение испортил.
>Если просто нужен функциональный язык то есть широкий ассортимент лиспов
Типы, братан. Хаскель умеет генерировать бесплатные термы из нихуя, тем самым обеспечивая корректность по построению и сильные гарантии на стадии конпеляции без особых усилий (со стороны разработчика, использующего подходящие библиотеки). На хаскеле стоит писать если ты готов лишний раз поебаться с типами, чтобы потом не ебаться со всем остальным.
Еще больше строгой статической типизации
Во-первых, тем, что система типов гораздо более выразительная, причём настолько, что дальше идут разве что зависимые типы. Из всех production-ready языков у хаскеля типы наиболее понтовые.
Во-вторых, вообще, редкий язык предоставляет такие возможности для автоматической генерации кода. Это что-то на уровне лисповых макросов, только половину работы компилятор делает самостоятельно, глядя на типы.
Все разговоры о корректности в контексте хаскеллевской системы типов могут заставить человека думать о какой-то магии, которая сама умеет отлавливать ошибки в программах. Это не верно, Хаскель никак не страхует от ошибок в алгоритмах. На самом деле Хаскель не про корректность, а про декомпозицию программ. Библиотеки для Хаскеля - это конструкторы, из которых можно собирать что угодно. А "сильные гарантии" - это гарантии того, что ты правильно комбинируешь детальки этих конструкторов. Лисп - это тоже конструктор. Но Хаскель - это LEGO, который не позволит тебе соединить детальки неправильно. А Лисп - это The Incredible Machine, в котором результат ты узнаешь только после того, как нажмёшь на кнопку Play.
>разумнее взять Эрланг
С хуёв ли разумнее? В Эрланге только довольно убогая модель акторов, в Хаскеле куда больше возможностей для построения различных примитивов синхронизации, в том числе поддерживающих автоматическую композицию.
Всё так, гарантии обеспечиваются системой типов. Но тип - это частичная спецификация, и иногда из одного только типа можно сгенерировать подходящий терм, корректный по построению. Вполне себе магия тащемта.
магия - это то, что ты не понимаешь
рекурсия ++ рекурсия - работает
http://tpcg.io/TT6zaU
(рекурсия : рекурсия) : [] - не работает
http://tpcg.io/UGqpCH
Что я делаю не так?
Конструктор (:) принимает голову списка и хвост списка. Оператор (++) принимает два списка.
Пожалуйста, обращайся.
Вы видите копию треда, сохраненную 12 ноября 2018 года.
Скачать тред: только с превью, с превью и прикрепленными файлами.
Второй вариант может долго скачиваться. Файлы будут только в живых или недавно утонувших тредах. Подробнее
Если вам полезен архив М.Двача, пожертвуйте на оплату сервера.