СоХабр закрыт.

С 13.05.2019 изменения постов больше не отслеживаются, и новые посты не сохраняются.

H О Haskell по-человечески в черновиках Из песочницы

Приветствую всех Хабражителей!

Представляю вашему вниманию книгу о языке Haskell. Впрочем, «книга» — это громко сказано: 160-страничное руководство для обыкновенных программистов, которые хотят наконец понять, как же можно жить без оператора присваивания и что такое монада.

Озвучу причины, с чего это вдруг мне, самому заурядному C++-разработчику, взбрело в голову написать про Haskell.

Причина первая: любовь со второго взгляда

Ничего примечательного о себе сообщить не могу. 7 лет опыта разработки на C++, год на Objective-C. Впервые услышал о Haskell случайно: у коллеги на столе лежала книга на английском языке «Programming in Haskell». Спросил. Услышав об отсутствии оператора присваивания, сначала не поверил своим ушам, а потом поспешил забыть про этот «функциональный ужас».

Второй взгляд на Haskell был уже более пристальным. Я решил разобраться, как же можно написать что-то на таком языке. Начал пробовать, разбираться. И потом понял, что это моё. Не знаю почему, но зацепило меня, и зацепило крепко. Может, сказались годы программирования на C++, не знаю… Уставать я начал от сложности C++, потому и Objective-C понравился мне сразу, потому и в Haskell влюбился по уши.

Причина вторая: эксперимент

Ни в школе, ни в ВУЗе я не любил математику и, как следствие, был в ней откровенно слаб. А вокруг Haskell, имеющего давние математические корни, сформировался стойкий стереотип: этот язык — для выпускников МФТИ, не ниже. И я подумал: «Если этот стереотип верен, то у такого как я нет ни малейших шансов освоить Haskell. Ну а уж если я смогу — значит другие тоже смогут». И я решил попробовать. Попробовал. Скажу одно: стереотип этот — ложь.

Причина третья: достало!

При всём моём уважении к авторам русскоязычных трудов по Haskell, большинство из них не годятся для новичков. Открываю — а там про быструю сортировку и факториал. Да не знаю я что это такое! И не хочу знать, потому что мне в моей работе не приходится иметь с этим дело. На пятой странице — про интегрируемость по Лебегу, на двадцатой — про моноид в моноидальной категории эндофункторов. А из самых первых примеров кода вижу что-то наподобие этого:

unfoldr (\b -> fmap (const . (second $ drop 1) . break (==' ') $ b) . listToMaybe $ b)

Простите, что это?..

Я решил руководствоваться мудрым афоризмом Альберта Эйнштейна: «Если вы не можете объяснить свою теорию шестилетнему ребёнку, значит вы и сами её не понимаете.» Именно поэтому решил написать так, чтобы понятно было любому.

Причина последняя: вклад

Недавно мне исполнилось 33. Пора уже не только брать от сообщества, но и что-то отдать ему. Я кое-что понял о Haskell, и хочу теперь поделиться этим со всеми моими коллегами. Штука-то ведь и вправду сильная оказалась…

Что в книге?

Основы основ. От cabal до Hackage, от чистых функций до списков, от пользовательских типов до обработки исключений, от функций высшего порядка до функторов.

Что будет дальше?

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

Собственно, вот книга: ohaskell.ru. Выпущена на CC-лицензии, так что распространение всячески приветствуется.

Благодарности

Благодарю авторов книг «Real word Haskell» и книги со слоном («Изучай Хаскел во имя добра»). Из этих книг я понял, что Haskell пригоден далеко не только для факториала. Благодарю Антона Холомьёва, автора учебника по Haskell. Также благодарю авторов многочисленных блогов, исследование которых помогло мне понять, что же такое эти монады и с чем едят частичное применение функции.

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

комментарии (138)

0
VoidVolker ,   * (был изменён)

Да, хорошее начинание! Я вот тоже некоторое время назад начал проходить один из популярных онлайн-курсов по хаскелу и забросил в середине — ибо как-то не то, а штука-то вроде как и интересная. Возможно, данная книга позволит понять наконец, что это такое «хаскел» :)

0
G0ran ,   * (был изменён)

А что за популярный онлайн-курс по хаскелю? Ссылку не дадите?:)

+2
k12th ,  

Планируются ли другие форматы, помимо PDF?

+2
denisshevchenko ,  

Да, планируются. FB2, EPUB, MOBI. Уже несколько читателей обратились ко мне с такой просьбой, поэтому я удовлетворю их просьбу в скором будущем.

+5
peinguin ,  

HTML, пожалуйста.

+1
denisshevchenko ,  

Очень скоро. Налёл очень неплохой способ конвертации в весьма красивый XHTML. Сохраняется всё, кроме, пожалуй, буквиц в начале глав. Но я уже начал улучшать коды примеров (в соответствии с озвученными здесь замечаниями и пожеланиями), так что прошу немного подождать.

+2
Shchvova ,   * (был изменён)

Спасибо огромное! Прямо то что хотелось и пока очень нравится. Очень хотелось бы несколько штук.
* Кнопку для донейшнов, ну, или как пожелаете
* Версию книги которую удобно читать с экранов: html, или что-то похожее. Страницы PDF как-то не удобно. Если уж книга и так СС лицензии, разве что-то мешает выложить ее исходники что бы желающие могли собирать свой любимый формат, или что-то такое. Ну или на гитхаб, что бы править ошибки в прозрачном виде.
Вообще это не важно. Потому что Вы сделали отличную работу, и я очень за это благодарен!
Edit: понятия не имею почему это ответом а не отдельным коментарием, но это и не важно, похоже. Добра!

+1
denisshevchenko ,   * (был изменён)

Большое спасибо за ваш отзыв!

Кнопку для донейшнов, ну, или как пожелаете

Подумаю.
Версию книги которую удобно читать с экранов: html, или что-то похожее. Страницы PDF как-то не удобно. Если уж книга и так СС лицензии, разве что-то мешает выложить ее исходники что бы желающие могли собирать свой любимый формат, или что-то такое. Ну или на гитхаб, что бы править ошибки в прозрачном виде.

Буквально час назад думал об этом. Наряду с пожеланиями форматов для «читалок», HTML вариант тоже был бы полезным. Я обязательно продумаю этот вариант.
+1
denisshevchenko ,  

Добавил кнопку для донейшнов.

0
vk2 ,  

Сделайте любой! дальше все конвертируется тем же Calibre. Очень хочу залить вашу книгу в читалку.

0
denisshevchenko ,   * (был изменён)

Очень скоро. Уже нашёл способ конвертации в (нормального вида) FB2. Но я уже начал улучшать код примеров (в соответствии с озвученными здесь замечаниями и пожеланиями), так что прошу немного подождать.

+2
denisshevchenko ,  

Готово. Теперь на сайте две кнопки, для PDF и для EPUB. Прошу не судить очень строго, это мой первый опыт работы с EPUB.

0
k12th ,  

Огромное спасибо!

0
mibori ,  

Для новичков всё очень круто, спасибо.

Скажите, а вы намеренно используете такой_стиль? (всё таки вХаскеллеПринятТакой)

+2
+4 –2
denisshevchenko ,  

Да не то чтобы намеренно… Просто такой_стиль принят в boost, а всё-таки привычка семилетней разработки на С++ сказывается. К тому же в некоторых пакетах из Hackage я видел такой_стиль вместо такогоСтиля. Но, думаю, что в следующем издании я изменю это, чтобы было привычнее для других Haskell-разработчиков.

+1
ArtyomKazak ,  

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

+17
+18 –1
Archarious ,  

Я, как человек, ничего не знающий о Haskell, хотел бы в начале книги увидеть ещё и рекомендации по применению этого языка.
Я имею в виду прикладные ненаучные области, где нам будет важен и критичен переход к функциональному декларативному языку, а также указания и рекомендации зачем, кроме личного удовлетворения, отказываться от привычных структур, вникать в функторы и монады. Вот, например, NoSQL советуют применять в «высоконагруженных» проектах, JavaScript не применять для сложной математики, и т.д…

А руководство ваше я уже скачал, пролистал и обязательно прочту на выходных. Пока что из личного интереса и любопытства как заурядный C++ разработчик :)

+7
+8 –1
Terranz ,  

инкрементирую

+2
achekalin ,   * (был изменён)

Спасибо! Правда.

P.S. На сайт зашел, и глаза в кучу: русский шрифт как шрифт, латинские буквы в два раза уже. Это by design, или просто выбран шрифт, которого у меря в русском начертании в системе нет? У меня в этом смысла самая обычная машина, без извратов, так что подобное может приключиться не только у меня…

Посмотрел: похоже, оно у Вас в теме WP прописано. У Вас на машине как выглядит?

+2
denisshevchenko ,  

Да, со шрифтом, это моя ошибка. На Mac и iPad шрифт выглядит великолепно. Причём русские и латинские буквы одного размера и начертания. А вот на Windows забыл проверить.

Я поправлю это в ближайшем будущем.

+2
mibori ,  

Погуглил абаркадабру сверху. Кому интересно — это, функция которая разбивает строку на слова.

words = unfoldr (\b -> fmap (const. (second $ drop 1). break (==' ') $ b). listToMaybe $ b)

> :t words
words :: [Char] -> [[Char]]

> words «Useful Idioms that will blow your mind (unless you already know them :)»
[«Useful», «Idioms», «that», «will», «blow», «your», «mind», "(unless", «you», «already», «know», «them», ":)" ]

Это конечно плохой для понимания код, но использование second понравилось.

+5
ArtyomKazak ,   * (был изменён)

Кому ещё интереснее – вот объяснялка.

unfoldr – это такой чудный универсальный генератор. На каждом шаге он скармливает функции что-то, а потом спрашивает: “ну как, понравилось”? Если не понравилось (функция вернула Nothing) – кормёжка прекращается. Если понравилось – функция выдаёт какой-то результат + определяет, чем её будут кормить в следующий раз. Потом unfoldr собирает результаты в список и выдаёт.

Пример:

> let step n = if n == 0 then Nothing else Just (intToDigit $ mod n 2, div n 2)
> let toBinary = reverse . unfoldr step
> toBinary 1337
"10100111001"

Теперь мы хотим написать функцию step такую, что она выдаёт Nothing, если слов в строке больше нет, и Just (слово, остаток строки), если есть. Поехали.

Разобъём строку:

> break (== ' ') "before after"
("before"," after")

Второй элемент пары начинается с пробела. Непорядок. В Control.Arrow есть функция second, которая умеет применять функцию “внутри” пары:

> second (drop 1) $ break (== ' ') "before after"
("before","after")

Обратите внимание, что вместо tail используется drop 1 – это для того, чтобы не было исключения на пустом списке.

> tail []
*** Exception: Prelude.tail: empty list
> drop 1 []
[]

Отлично, но надо ещё выдавать Nothing, когда строка пустая. Это просто:

> listToMaybe []
Nothing
> listToMaybe [1,2,3]
Just 1

Этакая headMaybe с кривым названием. Вот мы умеем получать Nothing или Just что-угодно, если список не пустой. Теперь надо “засунуть” то, что нам надо (пару со словом и остатком строки) внутрь. fmap применяет функцию к значению внутри Just; а const строит функцию, которая всегда возвращает одно и то же значение.

> fmap (+1) (Just 7)
Just 8
> fmap (const 13) (Just 7)
Just 13

Можно и проще (не знаю, почему в оригинале не так):

> 13 <$ Just 7
Just 13

Собираем кусочки воедино (следите внимательно):

> let test = "before after"

> break (== ' ') $ test
("before"," after")

> (second $ drop 1) . break (== ' ') $ test
("before","after")

> (const . (second $ drop 1) . break (== ' ') $ test) $ undefined
("before","after")

> fmap (const. (second $ drop 1) . break (== ' ') $ test) $ Just undefined
Just ("before","after")

> fmap (const. (second $ drop 1) . break (== ' ') $ test) . listToMaybe $ test
Just ("before","after")

> let step b = fmap (const. (second $ drop 1) . break (== ' ') $ b) $ listToMaybe b

> unfoldr step "bird is a word"
["bird","is","a","word"]

Ну и наконец, получившаяся функция почти что бесполезна. И вот почему:

> unfoldr step " bird   is a word"
["","bird","","","is","a","word"]

> words " bird   is a word"
["bird","is","a","word"]
0
mibori ,  

а потом, поигравшись, можно посмотреть как words реализована в Data.List

hackage.haskell.org/package/base-4.6.0.1/docs/src/Data-List.html#words

:)

0
ArtyomKazak ,  

Так суть игры была не в том, чтобы написать words (боже упаси), а в том, чтобы люди узнали про (относительно) редко используемые функции стандартной библиотеки и могли их применять по мере необходимости. Разумеется, заменять определение в три строчки подобным нагромождением – это перебор.

+1
mibori ,  

Безусловно.

Но среди игроков могут попасться и неуравновешенные, которые скажут "&^$%#@$! И эту ^%$#@ я должен продакшен пихать, чтобы только разбить строчку на слова?!".

+1
ArtyomKazak ,  

Наверное, стоило в начале добавить disclaimer: никогда не пишите words так и не думайте, что те, кто пишут, поступают правильно (такой же дисклеймер должен стоять перед якобы “быстрой сортировкой” в одну строчку).

А ещё неплохо читать исходники стандартной библиотеки на ночь. Я примерно так и начинал изучать Haskell – в Крыму вся семья купалась в море, кушала шашлык, а я сидел букой и читал с экранчика PSP исходники. (Не рекомендую этот способ тем, кто хочет процесс быстро и результат сразу – для таких лучше начать писать какое-нибудь web-приложение на Yesod и разбираться по ходу дела.)

0
feligz ,  

А что отличная объяснялка :) без заумных определений, все лаконично и понятно. Вам бы тоже может книжку по Haskell написать, для начинающих, думаю отлично бы получилось.

0
ArtyomKazak ,  

Книжек для начинающих и так много. На английском вообще полно (книги + туториалы + посты в блогах), на русском есть LYAH, и издательство Питер собралось переводить Beginning Haskell: A Project-Based Approach. А книг по “advanced Haskell” нет – остаётся только спрашивать на Haskell-Cafe или в #haskell, когда что-то неясно, или копаться в исходниках. Я бы и рад написать, но самому не хватает знаний.

Если хочется ещё объяснялок на несложные темы, можно устроить Q&A здесь в комментариях.

+1
evocatus ,  

Добавьте на главную страницу информацию о лицензии на книгу.

0
denisshevchenko ,  

Так в самой книге же есть! Значок со ссылкой на creativecommons.org/licenses/by-nc-sa/4.0.

Или вы имеете в виду на главной странице сайта?

0
denisshevchenko ,  

Добавил.

–2
+9 –11
skryzhanovsky ,  

Вы 33-летний программист на C++, не знающий, что такое факториал и quicksort? Это не для художественного эффекта написано было?

Почему спрашиваю, собсно. У вас по книге фоном какой-то «обычный программист», который то этого не знает, то того не знает. Может, дальше вскрывается, что он кандидат наук, но на старте ощущения странные. Я сейчас по контакт-листу пробежался, опросил 1 менеджера и 4 фронтендеров (CSS, HTML, Javascript) — факториал не посчитал только один фронт. Двое сходу дали определение, а один начал меня пытать на тему корпускулярно-волнового дуализма. Программистов решил не трогать, т.к. там сплошь читерство получится — матфак и физфак.

Очень советую хотя бы факториал из примера «для обычных людей» убрать. Обычные люди всё-таки не настолько… кхм, обычные. :)

–14
+1 –15
skryzhanovsky ,  

Ребятки, решившие минусовать, вы-то минусуйте, но потом погуглите факториал. :) Поймёте, насколько это детская и простая штука. Её даже бабушке с вековым филологическим стажем объяснить в пять минут можно. А тут о программистах речь.

+3
withkittens ,  

Ещё один истеричка? Вам на текущий момент поставили всего один минус, а вы уже готовы разразиться ехидным комментарием.

«Детское знание», «детское знание»… по вашему собственному опросу что такое факториал не знают 20 % (!) — 2 из 10. Вот вам и «детское знание». А ещё около 30-40 % населения России (точную цифру не помню) не знают, в каком порядке идут цвета флага нашей необъятной страны. Задумайтесь, возможно вы слишком хорошего мнения об «обычном» человеке.

–4
+1 –5
skryzhanovsky ,   * (был изменён)

Нет, не истеричка. Нет, комментарий не ехидный, даже ещё не начинал. Не готов, но разразился.

Задумайтесь, что речь идёт о программистах. Знания остального населения планеты вне пределов этой темы меня не интересуют. Представление о знаниях «обычных программистов» интересует. Представление о программистах, не знающих, что такое факториал, интересует.

+7
+10 –3
denisshevchenko ,   * (был изменён)
Вы 33-летний программист на C++, не знающий, что такое факториал и quicksort? Это не для художественного эффекта написано было?

Почти. :-) Разумеется, что такое факториал и что такое быстрая сортировка я знаю. Но знаю я это лишь потому, что, наткнувшись на эти термины в трудах по ФП, решил разобраться. Но вот реализовать алгоритм быстрой сортировки с нуля я бы сейчас не смог. Если бы мне это понадобилось в моей работе — да, я бы изучил и реализовал. Но пока не понадобилось.
У вас по книге фоном какой-то «обычный программист», который то этого не знает, то того не знает.

Да, обычный программист не знает большинство математических терминов, на которые с первых же страниц ссылаются авторы многих книг по Haskell (и по ФП в целом). Разумеется, когда мы учились на втором курсе ВУЗа, мы это знали. Но потом, закончив ВУЗ и проработав над неакадемическими задачами пару-тройку лет, мы это благополучно забыли. Нет, не все из нас, но большинство. И вот когда такой обычный программист открывает книгу «Введение в ФП», что он ожидает? Введение. А что он видит на самом деле? Главу про лямбда-исчисление с рассказом о том, почему «функция не интергрируема по Лебегу в пределах [0,1]»

Я считаю, что не знать то, что мне не нужно в каждодневной работе — это не стыдно.
–3
+2 –5
skryzhanovsky ,  

Ведь не про большинство терминов. Я ровно про те два термина, за которые зацепился взгляд. И даже быструю сортировку решил почти не упоминать, т.к. ок, её не пишут, т.к. обычно она уже написана в стандартных библиотеках. Но факториал-то! Повторюсь: это очень детское знание. Продолжил опросы: 2 сисадмина — знают, +2 (к предыдущим) фронтендера — знают, +1 (к предыдущим) фронтендер — ответил «не помню», считаем в незнающих.

+4
+6 –2
denisshevchenko ,  

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

То есть я ничего не имею против факториала, тем более что вопрос действительно простой. Но я против того, когда с этого начинают.

0
+1 –1
ImLiar ,   * (был изменён)

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

+3
ImLiar ,   * (был изменён)

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

имхо, довольно интересные цифры

0
JustSkiv ,  

А можно поинтересоваться, о какой книге идет речь в цитате про интегрируемость по Лебегу? Просто стало вдруг интересно.

0
denisshevchenko ,   * (был изменён)

John Harrison «Введение в функциональное программирование».

Классическое начало с примером про факториал, и уже на 7 странице, в самом начале второй главы, читаем: «Тогда f'(x) не интегрируема по Лебегу в пределах [0; 1].»

Справедливости ради должен отметить, что эта книга «основана на конспектах лекций по курсу Введение в функциональное программирование, который я читал в университете Кембриджа в 1996/7 учебном году. Курс читался студентам последнего курса и аспирантам первого года обучения.» Я более чем уверен, что студенты последнего курса в Кембридже прекрасно знают математическую нотацию и терминологию. Даже я, учась в значительно менее известном ВУЗе, знал её неплохо. Но потом забыл почти полностью.

0
ArtyomKazak ,   * (был изменён)

Ради ещё большей справедливости должен заметить, что это классический пример выдирания цитаты из контекста.

λ-исчисление основывается на так называемой ‘λ-нотации’ для обозначения функций. В неформальной математике, когда кто-то хочет сослаться на функцию, то обычно сначала дает этой функции произвольное имя, а затем использует его, например:
Предположим, что f ​: R → R определена выражением:
[.​.​.выражение...]
Тогда f'(x) не интегрируема по Лебегу в пределах [0, 1].

Это была рандомная цитата, которую автор “Введения” взял из какого-то математического учебника и привёл для иллюстрации “ссылки на анонимную функцию”. Интеграл по Лебегу тут вообще ни причём, можно было оставить только первую строчку (“Предположим, что f ​: R → R определена выражением...”) и пример все равно был бы понятен.
0
denisshevchenko ,   * (был изменён)

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

0
ArtyomKazak ,   * (был изменён)

Что-то вроде

Теорема 2.1. Для произвольного λ-терма s множество FV(s) конечно. Доказательство...

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

Книгу Харрисона стоило переименовать в “Введение в теоретические основы функционального программирования” для избежания путаницы. (А ещё есть “Мягкое введение в Haskell”, которое на самом деле… ну, не очень “мягкое”. М-да.)
+1
denisshevchenko ,   * (был изменён)

Опять-таки, я ничего против математики не имею. Более того, начав изучать Haskell, я сам становлюсь в каком-то смысле ближе к математике. Если кто хочет изучить теорию категорий — пожалуйста. Да и в математической нотации ничего сверхсложного нет. Однако я искренне не понимаю, зачем в учебник по Haskell, рассчитанный на новичков, включать (пусть даже и краткое) описание этой самой теории категорий. Зачем? Да, понятие «монада» пришло оттуда. Но это лишь термин. Программную сущность монадических цепочек можно понять и без этой теории.

0
kosiakk ,  

Для программистов, привыкших к имеративному стилю записи и для остальных людей, мне кажется, привичныее было бы использовать нотацию как в F#:

main =  replicate 100 "127.0.0.1"
     |> take 2 
     |> print

Оно и на unix-пайпы похоже.

С оговоркой, что
a |> b = b(a)


Вместо
main = print (take 2 (replicate 100 "127.0.0.1"))
0
denisshevchenko ,  

Вероятно, вы правы. Просто я счёл эту цепочку из трёх функций настолько тривиальной, что не подумал о переформатировании. Спасибо за совет!

+1
Shekeen ,  

Но вообще на Хаскеле вместо

main = print (take 2 (replicate 100 "127.0.0.1"))

чаще пишут
main = print $ take 2 $ replicate 100 "127.0.0.1"


Да и композицию функций стараются писать в прямом (математическом) стиле, через точку, а не через пайп, как в F#.
Но тут, конечно, кому как удобнее.
0
+1 –1
kosiakk ,   * (был изменён)

Принято, да. Но меня, как новичка, знаки доллара пугают =)

+1
denisshevchenko ,  

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

+1
Wyrd ,  

Про это написано в тексте книге ниже.

+1
artemonster ,  

Спасибо! оч круто!

+2
ArtyomKazak ,  

Придирки по мелочи.

Страница 3:

Запомнили? А теперь можете забыть. Особенно про интерпретатор.

Да интерпретатор же – самая полезная вещь! Вот написали вы функцию, гадаете: работает или нет. Что, сразу юнит-тесты начнёте писать? Или в main добавлять что-то вроде mapM_ (print . my_func) [test_1, test_2, test_3]? Ведь гораздо удобнее работать с кодом, загруженным в интерпретатор – можно вызывать любые определённые функции с любыми параметрами. (И это не говоря о том, что GHC вообще компилирует довольно медленно, так что интерпретатор сильно экономит время.)

Страница 72 (и ещё много где):

(fst pair) ++ "-" ++ (snd pair)

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

Страница 78:

ends_with :: String -> String -> Bool
ends_with str suffix = endswith suffix str

А вот нет бы рассказать про flip, который в книге (если верить Ctrl-F) вообще ни разу не упоминается…

Страница 80:

Как только натыкаемся на собачку — возвращаем всё, находящееся перед ней.
Вот и всё. Теперь вы знаете, что такое list comprehension и как его можно
использовать в вашем коде.

Ну, почти всё. Ещё можно писать что-то вроде [f a | let m = a `mod` 7, m /= 2, m /= 5] – когда в нескольких предикатах есть повторяющийся кусок, лучше вынести его в let.

Страница 124:

where starts_with = \url prefix -> startswith prefix url

Глобальную функцию вы бы ведь нормально объявили – “starts_with url prefix = ...” – а чем локальная функция провинилась?
+1
denisshevchenko ,  

Большое спасибо за ваши замечания! Обязательно учту.

0
andymitrich ,  

А вот спасибо вам! Давно хотел Haskell начать изучать, вот сижу теперь с вашей книжкой.

+1
not_ice ,  

За вывод профиля пользователя на Хаскеле — прям отдельный респект :)
А можете рассказать — какие-то коммерческие проекты были вами разработаны целиком на Хаскеле? И какого плана эти проекты?

0
denisshevchenko ,  

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

Впрочем, уже сейчас, взирая на С++-код своего FastCGI-сервера, я постоянно ловлю себя на мысли, мол, «А вот на Хаскеле я бы это сделал вот так...» :-)

+2
uvelichitel ,  

Я так понимаю трансформеры монад и аппликативные функторы оставлены для самостоятельного освоения вдумчивому читателю?

+1
denisshevchenko ,   * (был изменён)

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

+1
uvelichitel ,  

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

0
denisshevchenko ,  

Фактически, с аппликативными функторами и монадными трансформерами я уже почти разобрался. Мне нужно только подобрать понятные примеры и простые объяснения к ним, ну и добавить в книгу.

+2
ArtyomKazak ,  

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

Господа гусары! Если вам когда-нибудь хотелось применить функцию к всяким штукам, а эти штуки все пообёрнуты в монады – не спешите писать do-блок и разворачивать их! Просто перед первой штукой поставьте <$>, а перед прочими – <*>, и дело в шляпе!

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

Ради пущего интереса стоит привести пару примеров:

Гусары склеивают две строчки:

twoLines = do
  a <- putStr "line 1: " >> getLine
  b <- putStr "line 2: " >> getLine
  return $ a ++ b

Поручик клеит строчки:

twoLines = (++) <$> (putStr "line 1: " *> getLine) 
                <*> (putStr "line 2: " *> getLine)

Гусары пишут парсер для натуральных чисел:

naturalP :: Parser Integer
naturalP = do
  firstDigit <- oneOf ['1'..'9']
  rest <- many $ oneOf ['0'..'9']
  return $ read $ firstDigit : rest

Поручик безжалостно парсит числа:

naturalP :: Parser Integer
naturalP = fmap read $ (:)
  <$> oneOf ['1'..'9']
  <*> many (oneOf ['0'..'9'])
0
denisshevchenko ,  

Благодарю за пример!

+2
denisshevchenko ,  

Я уже почти закончил написание главы про аппликативные функторы. Очень классный инструмент!

Войдёт в издание 0.3.

+3
Wyrd ,   * (был изменён)

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

Объясню, что я имею в виду.
[просьба учесть, что хаскелем я владею на очень примитивном уровне — интересовался когда-то из любопытства].

Допустим, у нас есть некая функция String -> String.
В процессе разработки часто оказывается, что мы где-то что-то забыли.
Например, обработать ошибки: тип функции приходится изменить на Maybe String -> Maybe String (или Maybe String -> String — зависит от ситуации).

И тут начинаются проблемы: если функия сколько-нибудь сложная, монада Maybe начинает «разъезжаться» по всей внутренней логике, вызывая «пандемию». Это очень похоже на «пробрасывание» дополнительных параметров в императивных языках через дебри внутренней логики.

Добавлю, что данная проблема с моей неопытной точки зрения является одной из самых значительных преград в Хаскеле.
Особенно ярко, насколько я помню, это проявляется при «пробрасывании» монады IO.

Возможно, есть какое-то универсальное лекарство от монадической пандемии?

0
Wyrd ,  

И еще хотелось бы освещения:

1. Юнит-тестирования и ТДД-практик в хаскеле
2. Того, как же код хаскеля, черт возьми, превращается в бинарный код. Какие он умеет применять оптимизации, как быстро он выполняется?

+1
denisshevchenko ,  

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

+3
ArtyomKazak ,  
Это очень похоже на «пробрасывание» дополнительных параметров в императивных языках через дебри внутренней логики.

Именно. Эта проблема универсальна для всех языков, и лечится похожим образом во всех языках.

  • Все куски кода, которым не нужны дополнительные параметры, выносятся в отдельные функции.
  • Если параметры нужны всем функциям, оборачиваем их в Reader.
  • Я, например, в своих программах завожу монаду ProgramName, и всё программно-специфическое у меня работает в этой монаде. Могу туда добавить параметры, State, Maybe, IO – а код при этом не меняется (в этом сила монадных трансформеров).
  • Старайтесь обрабатывать ошибки как можно раньше. Если тип функции меняется с a -> b на a -> Maybe b – посмотрите, может, вам удастся обработать Nothing во всех функциях, использующих ту функцию, и остановить пандемию?
  • Если не удалось – кидайте Exception и обрабатывайте его там, где удобно.
  • Наконец, если внезапно оказалось, что самой часто используемой функции в вашей программе нужно прочитать значение из файла, чтобы, скажем, определить, в какую сторону надо округлять числа… unsafePerformIO. Но это исключительно на вашей совести, только в чрезвычайных ситуациях, и стыдно рассказать детям.
0
Wyrd ,  

Спасибо, то что хотелось услышать.

+3
mibori ,  

ArtyomKazak хорошо рассказал.

Алсо, монады, как паттерн проектирования призваны разделить код одного вида (допустим, парсинг) от кода другого вида (допустим, операциями ввода вывода).

Хорошим, несложным примером этого является стандартная функция interact :: (String -> String) -> IO ()

Первый аргумент у нее — чистая функция, которая процессит строку и отдает строку. Эта функция потом используется interact для ввода/вывода в stdin/stdout. Так вот, надо стараться отделять чистый код, от кода ввода/вывода; и в общем код, который занимается одним, от другого. Если об этом не задумываться, будет монадический ад и никакого удобства. Как раз почти этим мы занимаемся, когда в больших проектах у нас концентрируются небольшие библиотеки (которые можно перенести в другой проект). Своего рода, что считается хорошим тоном в других языках, то в Хаскелле способ написания без дальнейшего геммороя.

Надеюсь хорошо получилось выразить философскую мысль.

0
Wyrd ,  

Да, спасибо, об этом я думал (проводя параллели с отделением бизнес логики в других языках). Но вопрос был именно о том, что делать, когда монаду действительно «забыли» или не поставили умышленно (в процессе прототипирования).

0
denisshevchenko ,  
Так вот, надо стараться отделять чистый код, от кода ввода/вывода; и в общем код, который занимается одним, от другого.

Золотые слова. Жаль, что не все разработчики придерживаются этого принципа.
+1
Wyrd ,   * (был изменён)

Сделайте подсветку кода в книге.

Можно, например, использовать highlight.hohli.com
Он умеет подсвечивать код хаскеля.
Выдавает соответствующий HTML.
Примеры кода станут намного читабельней

p.s. Сама книга очень понравилась — просто и доступно :)

+2
denisshevchenko ,  

Спасибо за отзыв! А про подсветку я подумал с самого начала, но как-то поленился. Это мой недогляд. Обязательно сделаю.

0
Halt ,   * (был изменён)

Советую для единообразия оформлять стили по аналогии с тем как сделано в «практике».

+1
denisshevchenko ,  

Готово. В издании 0.2, которое вышло сегодня, добавлена подсветка (отдельно для примеров кода и для примеров терминальных команд). Теперь примеры читаются значительно проще.

+2
denisshevchenko ,  

Друзья! Я очень благодарен всем вам за советы, рекомендации и отчёты об ошибках. Никак не ожидал такого внимания к моему труду. Ваши отзывы многократно усилили моё желание продолжать, ведь я убедился, что Haskell интересует действительно многих разработчиков.

+1
Assargin ,  

Книга великолепна. Каждое предложение — в тему, отлично ложится на подготовленную (точнее, как раз, на неподготовленную) почву сознания обычного программиста, особенно если он когда-то заинтересовался предметом, но в силу теоретической неподготовленности не осилил другие материалы по теме.
Прочел запоем несколько первых глав, пропуская практические инструкции, и еле оторвался, всё же понимая, что лучше читать и делать сразу, отложив это всё на выходные.
P.S.: BTC в качестве благодарности принимаете?)

+1
denisshevchenko ,  

Большое спасибо за отзыв! Искренне рад видеть, как моя книжка помогает моим коллегам.

P.S.: BTC в качестве благодарности принимаете?)


Я добавил кнопку пожертвований от Яндекса. Просто у меня уже был профиль на Яндексе, ну я и завёл кошелёк. Форма пожертвований принимает, собственно, от Яндекса и от карточек Visa и MasterCard. BTC нету…
0
Vitalykurin ,  

Спасибо!

+1
dottedmag ,  

Хорошая книжка.

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

foo bar baz = xyz

— это то же самое, что
foo = \bar baz -> xyz

И в дальнейшем не делать различий между двумя формами записи.
0
denisshevchenko ,  

В процессе работы над следующим изданием код примеров будет переработан (добавлю подсветку и изменю такой_стиль на такойСтиль), и тогда я внесу поправки в форму функций.

Спасибо!

+1
denisshevchenko ,  

Сделано. Я учёл ваше пожелание в вышедшем сегодня издании 0.2.

+1
Kluyg ,  

Для тех кто решил попробовать Haskell и у кого OS X Mavericks (10.9 и выше) — обратите внимание на секцию «Xcode 5 & OS X 10.9 (Mavericks)» на страничке www.haskell.org/platform/mac.html
Если не сделать что там написано, то на этапе (из книги)
> cabal install text
вылезет куча ошибок.

0
denisshevchenko ,  

Спасибо большое за замечание. У меня OS X 10.7, поэтому я не знал… Учту.

+3
EvilsInterrupt ,  

А не могли бы Вы описать 1-2 боевых случая из своей практике где Haskel при ваших программерских навыках помог выполнить задачу лучше? Просто мне не очевидно с поста, стоит ли мне лезть и качать книгу и читать книгу, а чтобы это мне понять мне нужно скачать и прочитать первые 2-10 стр. Поэтому указание Вашего опыта на основе 1-2 примеров было бы кстати. IMHO

0
denisshevchenko ,   * (был изменён)

К сожалению, на данный момент я не могу предложить такое описание, поскольку практического опыта разработки на Haskell я на сей день и час не имею.

Именно поэтому я и решил серьёзно его изучить (в том числе разобраться в деталях, так сказать). Ведь я хочу сделать Haskell одним из своих каждодневных инструментов (а в идеале — инструментом №1).

0
EvilsInterrupt ,  

Ок. Задам Вам вопрос, решение которого я все время откладываю.
Задача:
Имеется файл header в терминах C++ проекта. В котором написано объявление базового класса с некоторым набором чистых виртуальных функций(проще говоря интерфейс). Надо по этому хидеру сформировать два новых файла *.hpp, *.cpp в которых будет сформирован код потомочного класса с реализацией методов в теле которых написано «throw std::runtime_error(»Unimplemented")".

0
denisshevchenko ,  

Простите, я не совсем понял вас… Это что, задача для Haskell?

0
EvilsInterrupt ,  

Мне кажется люди функционально мыслящие, решают задачи подобного типа значительно быстро. А Haskel поощряет функциональное мышление.

0
Wyrd ,  

Ваша задача полностью реализована здесь: www.jetbrains.com/resharper/features/cpp.html

+2
EvilsInterrupt ,   * (был изменён)

>>а в идеале — инструментом №1
Но почему именно Haskel? Ведь существует множество других языков поощряющих функциональное программирование. Возможно есть какие-то очевидные вещи, но я о них не догадываюсь. Недавно вот начал читать SICP(Structure Interpretation of Computer Programs) и мне показалась Sheme достаточно интересным инструментом из чего делаю вывод, что в последствии попробую Closure. Но другая часть мозга задает вопрос: «А почему Closure, есть же еще и Erlang?». Вот и мне интересно, почему Вы выбрали именно этот язык(Haskel)?

0
denisshevchenko ,   * (был изменён)

Вы абсолютно правы. Есть и Erlang, есть и Lisp, и Clojure, и Scala. Но лично мне Scala и Clojure не приглянулись в силу того, что они связаны с JVM. Да простят меня Java-разработчики, но лично мне нравятся языки, код на которых компилируется в нативный исполняемый файл.

Кроме этого, мне очень нравится высокоуровневый синтаксис Haskell, но это субъективная оценка. Частично на мой выбор повлиял и тот факт, что Haskell просто первым подвернулся мне под руку. Также мне очень понравилась система cabal.

Ну и потом, как сказал один герой старого фантастического фильма, «на ком-то ведь надо было остановиться»… :-)

0
Vitter ,  

Возможно ответ в том, что в Хаскеле нельзя написать (вернее можно, но сложнее) код императивного вида. И нельзя написать в ООП-виде код.
В то время, как другие ФП языки разрешают «императивщину». Вот люди и пишут на этих ФП языках как на своём любимом.

Ну, и ко всему у Хаскеля больше всего возможностей (функциональных фич).

Хотя и у Хаскеля есть свои проблемы, когда начинаешь переходить к промышленному программированию. Основная проблема — «кабальный ад». Это атавизм того, что язык создавался академическим (не для пользования). По идее уже найдены пути решения проблемы «ада», и думаю за год к следующему стабильному релизу GHC проблема будет снята.

0
denisshevchenko ,   * (был изменён)

cabal sandbox — это решение «кабального ада». Я об этом обязательно напишу в следующих изданиях.

Для ознакомления: coldwa.st/e/blog/2013-08-20-Cabal-sandbox.html

0
EvilsInterrupt ,  

А какой ассортимент типов приложений охватывает Haskel? К примеру протектор для Elf файлов можно? Если да, то насколько трудоемко? Можно ли дизассемблер написать и насколько читабельным будет код?

0
ArtyomKazak ,  

Можно и дизассемблер написать. Не очень удачный пример – в дизассемблере большую часть кода занимает логика, и причём логика эта очень близка к парсингу, а в этой области у Haskell есть преимущество благодаря Parsec / Attoparsec.

0
EvilsInterrupt ,  

У меня часто стоят задачи в ковырянии и анализе потока машинного инструкций. При анализе мне нужные значения опкодов, регистров, префиксов и др. вещи. На си уже привычно, привык и на Golang, даже на Java без ее прямой поддержки unsigned типов и то привык. А вот в Haskel пока не представляю как! ;)

0
Joshua5 ,  

прошу прощения, но наверное это не очень нормально, когда исполняемый файл первого примера в книге весит больше мегабайта (750к после strip)? ubuntu 13.10 (x86_64), если что.

0
denisshevchenko ,   * (был изменён)

Почему это не очень нормально? Сравните. Это зависимости исполняемого файла приложения на C++:

dshevchenko$ otool -L learn 
learn:
	libboost_date_time.dylib (compatibility version 0.0.0, current version 0.0.0)
	libboost_regex.dylib (compatibility version 0.0.0, current version 0.0.0)
	libboost_filesystem.dylib (compatibility version 0.0.0, current version 0.0.0)
	libboost_system.dylib (compatibility version 0.0.0, current version 0.0.0)
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)
	/Users/dshevchenko/Tools/GCC/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 7.17.0)
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
	/Users/dshevchenko/Tools/GCC/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)


а вот наш пример Real:

dshevchenko$ otool -L Real
Real:
	/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 159.1.0)
	/usr/lib/libiconv.2.dylib (compatibility version 7.0.0, current version 7.0.0)


Вот потому он и больше.
+5
ArtyomKazak ,   * (был изменён)

Нет, это нормально. Эти 750 килобайт занимает RTS – если хотите, можете сделать динамическую линковку, и будет 20 килобайт, но тогда придётся устанавливать shared libraries отдельно. Программы на Java тоже бы много занимали, если бы у каждого не было стомегабайтного рантайма на компе.

$ ghc -dynamic helloworld.hs
[1 of 1] Compiling Main             ( helloworld.hs, helloworld.o )
Linking helloworld ...

$ du -h helloworld
20K 	helloworld
0
denisshevchenko ,  

Я имел в виду, что исполняемый файл, написанный на том же C++ — он, как правило, небольшой, но тянет за собой специфические зависимости. А исполняемый файл на Haskell сравнительно больше, но специфических зависимостей нет.

+3
ArtyomKazak ,   * (был изменён)

А ещё есть такой компилятор JHC, он используется в embedded systems. Это, конечно, немного оффтопик, потому что новичкам пользоваться JHC не рекомендуется (не поддерживает некоторые функции GHC, другие сообщения об ошибках, нет интерпретатора), но всё же:

$ cabal install -j drift
$ cabal install -j ajhc

$ ajhc helloworld.hs -o hello
$ strip hello
$ du -h hello
20K	hello
$ ldd hello
	linux-vdso.so.1 (0x00007fff7f782000)
	libc.so.6 => /usr/lib/libc.so.6 (0x00007f3fb6523000)
	/lib64/ld-linux-x86-64.so.2 (0x00007f3fb68cb000)
0
Joshua5 ,  

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

0
+1 –1
Vitter ,  

хорошая книжка

+1
StreetStrider ,  

Подскажите, с помощью чего вы оформляете PDF? Вышло очень годно: сноски, ссылки в сносках, колонтитулы.

+1
EvilsInterrupt ,  

Может быть TeX?

0
m0nhawk ,  

Подскажу вместо автора: OpenOffice 4.0.1. В свойствах PDF такая информация хранится.

0
EvilsInterrupt ,  

Упс. Поленился посмотреть на сам документ. Вы правы ;)

+2
denisshevchenko ,   * (был изменён)

Как уже верно ответили, я делаю в OpenOffice. Кроме того, я ознакомился с базовыми принципами книжной вёрстки, чтобы моя книга выглядела, скажем так, «по-настоящему». :-)

0
StreetStrider ,  

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

0
EvilsInterrupt ,  

>>с базовыми принципами книжной вёрстки
На пример?

+2
denisshevchenko ,  

Мне хватило этих двух статей:

1. dpk-press.ru/oformlenie-knigi-sov
2. yuri-pavl.com/pravila/

Соблюдение (хотя бы большинства из) этих правил уже делает книгу книгой.

0
Rome ,  

Спасибо за книгу. Читаю pdf на iPad, там великолепно смотрится pdf.
Скажите, как вы вставляете код так, чтобы он не поломался, чтобы не закрался лишний пробел?

+3
denisshevchenko ,   * (был изменён)
Rome, Благодарю за отзыв.
Скажите, как вы вставляете код так, чтобы он не поломался, чтобы не закрался лишний пробел?

Я вставляю код на страницу, скопировав его прямо из Vim. Потом применяю к вставленному куску кода соответствующий стиль из OpenOffice — и в результате код на странице выглядит точно так же, как и в самом Vim.
+3
denisshevchenko ,   * (был изменён)

Рад сообщить вам, что издание 0.2 вышло в свет. Из новшеств:

— Добавление синтаксической подсветки для примеров кода и командной строки.
— Переработка синтаксиса примеров. Даже несколько ошибок нашёл!
— Изменение стиля кода с boost_like на camelCase.
— Исправление ошибок в тексте.
— Глава про hlint.

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

0
BooBSD ,  

Очень нужен вариант в формате ePUB!

0
denisshevchenko ,  

Я уже пробовал конвертировать в ePUB и в FB2. Таких конвертеров полно, как платных, так и бесплатных. Однако проблема у них у всех одна: в готовом ePUB/FB2 теряется моноширинный шрифт примеров кода. Выглядит не очень… Едва ли вас такое устроит… Или устроит?

+1
ArtyomKazak ,  

Попробуйте экспортировать в XHTML и потом создать ePub с помощью eCub.

0
denisshevchenko ,  

Огромное спасибо за совет! Я разобрался, что если конвертировать сначала из ODT в XHTML, а потом XHTML конвертировать с помощью Calibri в EPUB, то результат очень хорош.

В ближайшее время выложу.

0
ArtyomKazak ,  

Ух ты, так Calibre тоже умеет конвертировать из XHTML! А я и не знал.

Отлично, ждём с нетерпением.

+2
denisshevchenko ,   * (был изменён)

Готово. Прошу не судить строго, это мой первый опыт конвертации в EPUB. ohaskell.ru/get/ohaskell.epub

Там теперь две кнопки на сайте: для PDF и для EPUB.

0
Luxi ,  

К сожалению, на моем nook не работает. Вместо букв — знаки вопросов. Чтобы это починить — нужно при конвертации в ePub встраивать шрифты в сам документ. Наверняка Calibri такое умеет. Во всяком случае, веб-сервисы для конвертации точно умеют.

0
denisshevchenko ,  

Да, Calibre это умеет. Я просто не подумал, что это реально необходимо, потому что открывал в программных читалках и видел что там всё ок. Просто физической читалки у меня нет, так что «в живую» проверить не могу.

Я переконвертирую. Спасибо за замечание.

+2
denisshevchenko ,  

Попробуйте. Я переконвертировал со шрифтами. Судя по тому, что размер файла значительно увеличился, шрифты там действительно есть, так что всё должно работать.

0
Luxi ,  

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

И еще одно замечание: темный фон в примерах кода для e-Ink читалкок — не лучшее решение. У меня на нуке он еще и рябит ужасно. Читать очень тяжело. Лучше бы фон был белым. И шрифт мелковатый немного.

+1
denisshevchenko ,  

Тёмный фон убрал. Спасибо за замечание, на белом фоне действительно стало лучше. Я оставил обрамление слева и справа, в виде серой полосы для примеров кода и в виде чёрной полосы для терминальных команд.

По поводу шрифтов — я разберусь.

0
Luxi ,   * (был изменён)

Спасибо большое. Стало лучше.
Вот примеры некорректного отображения кириллицы:

i5.minus.com/jX5TJs7wH8wJV.jpg

i6.minus.com/jbhFR6ZDJh6eD8.jpg

i2.minus.com/jjVYdNwiP1Vgn.jpg

0
denisshevchenko ,  

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

+1
Atakua ,  

Начал читать, пока что впечатления положительные. Видно, что написано с душой и сделано со вкусом.
Но вот один вопрос терзает меня неимоверно. Страница 14, третий параграф:

И многие из нас, читая какой-нибудь труд, написанный аспирантом МФТИ, часто ловят себя на мысли, мол, куда уж мне до его мозгов...

И в этом посте:
стойкий стереотип: этот язык — для выпускников МФТИ, не ниже

Я сам недавний аспирант оного вуза и имею подобный труд. И у меня возникли опасения — неужели и вправду у физтехов вырабатывается «заумный» стиль письма, который невозможно читать? Я уверен, что никакой технический текст не должен вызывать у читателя сомнений в его (читателя) способностях. По крайней мере в книге могут присутствовать несколько «слоёв» для разного уровня подготовки или для разных прочтений. И, видимо, не всегда авторы способны выдержать необходимый баланс.

Вы можете развить свою мысль: почему МФТИ выбран как «эталон заумщины»? Я интересуюсь, потому что хочу и сам критически пересмотреть свою работу, и до будущих поколений постараться достучаться, чтобы не повторяли ошибок. Спасибо!
0
denisshevchenko ,  

Я с большим уважением отношусь к людям, учившимся в МФТИ. Более того, в студенческую бытность я лично соприкасался со многими из них. Классные ребята. Однако большинство из них (к счастью, не все) не были способны объяснить простому человеку (например, мне), чем они занимаются. Да, многие из них занимались действительно сложными вещами (скажем, физика жидких кристаллов), но, как говорил Альберт Эйнштейн, «если вы не можете объяснить свою теорию шестилетнему ребёнку, значит вы и сами эту теорию не понимаете».

Это не проблема МФТИ, нет! Подобное я наблюдал и у выпускников Бауманки, и МИФИ, и МГУ. К сожалению, умение простым языком объяснить сложные вещи присуще далеко не всем умным людям.

0
denisshevchenko ,  
По крайней мере в книге могут присутствовать несколько «слоёв» для разного уровня подготовки или для разных прочтений. И, видимо, не всегда авторы способны выдержать необходимый баланс.

Вы совершенно правы. К сожалению, этот баланс часто так перекошен, что читатель бросает книгу…
+1
EvilsInterrupt ,   * (был изменён)

Кстати у Вас не освещены достаточно важные темы:
1) Какие IDE популярны среди Haskel-девелоперов и какую используете лично Вы и почему?
2) Какие существуют способы связывания Haskel с другими языками? К примеру для Java есть JNI для просачивания в мир С\С++. Для Golang есть cgo. А какие для Haskel?

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

Итог от чтения:
1) Мне книга показалась сложной ;( Страшно представить другие книги по этому языку
2) Также мне показалось что Вы повторяетесь в своей книге про то зачем Вы ее пишите

Рекомендации:
С кусками кода поступить точно также как Брюс Эккель в своей книге про мышление на Java. Он выделил спец.тегами, написал скрипт и таким образом может выдирать из книги примеры и отправлять на компиляцию и тестирование, чтобы точно быть уверенным что читатель получает корректные куски кода

+2
denisshevchenko ,  
Кстати у Вас не освещены достаточно важные темы:
1) Какие IDE популярны среди Haskel-девелоперов и какую используете лично Вы и почему?

Я не использую IDE, только Vim и терминал.

Что касается IDE для Haskell, то лично я знаю лишь одну: Leksah (http://leksah.org/). Она примечательна тем, что, будучи средой для разработки на Haskell, сама написана на Haskell.

2) Какие существуют способы связывания Haskel с другими языками? К примеру для Java есть JNI для просачивания в мир С\С++. Для Golang есть cgo. А какие для Haskel?

Haskell интегрируется с языками C и C++. Причём в обе стороны: можно из Haskell-кода вызывать C-код, можно наоборот. Эта тема обязательно будет рассмотрена в следующих изданиях.

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

Обязательно! Они будут выделены в отдельные главы.

Итог от чтения:
1) Мне книга показалась сложной ;( Страшно представить другие книги по этому языку

Сложной? Хм… Поверьте, я старался писать так, чтобы понял любой программист. Если она показалась вам сложной — прошу прощения, но написать проще я бы не смог (по крайней мере, на данный момент).

Рекомендации:
С кусками кода поступить точно также как Брюс Эккель в своей книге про мышление на Java. Он выделил спец.тегами, написал скрипт и таким образом может выдирать из книги примеры и отправлять на компиляцию и тестирование, чтобы точно быть уверенным что читатель получает корректные куски кода

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

Благодарю за отзыв!
0
Shekeen ,  
Что касается IDE для Haskell, то лично я знаю лишь одну: Leksah (http://leksah.org/)

Есть еще облачная IDE — FP Haskell Center
Она, насколько я знаю, платная, но есть месяц триала, который можно оформлять каждые n (подставьте нужное n) месяцев, если ты в течение этих месяцев не пользовался этой IDE.

А вообще на Haskell довольно удобно писать в текстовом редакторе (мои фавориты — Sublime и Emacs). Но я, конечно, нерепрезентативен, т.к. на Haskell пишу только персональные и очень небольшие проекты.
0
denisshevchenko ,   * (был изменён)
Есть еще облачная IDE — FP Haskell Center

Ой, ваша правда! Про FP Haskell Center я даже и забыл. А ведь я у них даже пытался проходить Haskell School, хотя почему-то не пошло у меня…
0
EvilsInterrupt ,  

Недавно думал над тем почему же я не могу слезть с языка C++ и выявил для себя следующие вещи:
1) В других языках не увидел template на стадии компиляции. Мне это нужно для того чтобы можно было применять идиому traits. А она мне нужна потому что работаю с исполняемыми файлов которые делятся на 32- и 64-битные варианты. Как правило у них формат одинаковый, т.е. название структур, полей и расположение полей в структурах, отличие лишь только в некоторых типах полей uint32_t, uint64_t. И как вывод обобщить можно путем использования traits что приводит к унификации кода и избавляет писать две ветки кода.
2) Работа на низком уровне с битами, байтами, word, dword все-таки удобней в С\С++. Можно с натяжкой назвать Java, но там нет поддержки unsigned-типов. Т.е. различные операции shr, shl, ror, ror и др. вещи очень важны для меня. Они важны потому что достаточно часто мне надо проанализировать машинную инструкцию, если надо составить по байтно новую и др. низкоуровневые вопросы.