Если есть желание поизучать хаскели, есть тут у меня один могильничекнебольшой проект.
Проект сугубо прикладной.
У меня имеется также желание реализовать некоторые более грандиозные идеи, но пока нет времени. Например, дедуктивную субд с интерфейсом на даталоге, надмножестве sql.
Интересный момент, 3 человека поставили плюсы и 9 добавили в избранное.
По теме: возможно, все минусующие не испытывают потребности в поиске, выборе и приобретении книг. Или их потребности полностью покрываются другими способами.
Возможно, поэтому проект не стал достаточно популярным.
Кто живёт в правой части страны, посмотрите на японские 20 летние машины — управляются программируемыми контроллерами и всё ещё успешно ездят. Правда аптайм не непрерывный, но отказоустойчивость поражает. Железо и механические части умирают и заменяются новыми, а электроника как работала так и работает.
Интересно как использовать пролог в связке с другими языками и какую реализацию использовать?
Я так и не нашёл ни одной годной реализации, всё очень примитивно.
Выяснил, что SWI-Prolog это самая продвинутая реализация. Так вот это очень недоразвитый проект. Ничего практически полезного с ним сделать нельзя. Документация по интеграции с другими системами ужасная. Очень сложный сишный код, который периодически падает по непонятным причинам.
Например, code.google.com/p/pyswip/ — библиотека работы с swi-prolog из python. Есть аналогичная библиотека для хаскеля hackage.haskell.org/package/hswip. Попробуйте сделать с их помощью многопоточную программу. Чтобы с интерпретатором могли работать сразу несколько потоков. Это невозможно.
Я думаю что у пролога большое будущее. Но писать исполняемый код на нём большое извращение.
Пролог идеален только в качестве языка запроса к дедуктивным базам данных. В конце концов SQL это частный случай пролога. На прологе можно намного проще делать всякие outer join и выполнять рекурсивные запросы без использования хранимых процедур. Реально проще.
Немного ещё поразбирался, библиотеки парсеров здесь не используются. Есть только аппликативные функторы и Serialize — извлечение значений из байтовых потоков. Но смысл тот же.
Но главная проблема я так понимаю не в коде, а в обучении. Свежего человека отправляем на неделю или сколько ему нужно знакомиться с базовыми концепциями. В дальнейшем при встрече каждого непонятного смайлика опытный человек говорит ему куда копать, что читать и что чёрт возьми тут происходит.
Как быстро вольётся — сложный вопрос. Но есть же разные участки кода по сложности. Самые простые вещи, думаю, можно начать писать очень быстро.
Конкретно этот пример требует понимания только типов данных, монад, библиотеки parsec и аппликативных функторов. Точнее даже не аппликативных функторов, а операторов <$> и <*> из Control.Applicative. Они делают простые вещи.
-- | Parses a BInt
getBInt :: Get BCode
getBInt = BInt . read <$> getWrapped 'i' 'e' intP
where intP = ((:) <$> char '-' <*> getDigits) <|> getDigits
Ключевой момент здесь — тип Get a. Что это такое, я не знаю, в этом модуле не определён. Нужно найти откуда он импортируется и понять что он точно делает. По коду он похож на монаду парсинга, такую как в parsec.
getBInt :: Get BCode
Сигнатура функции говорит, что в этом месте из какого-то потока токенов, может быть строки символов, парсится значение типа BCode.
Описание типа BCode есть в этом модуле.
(.) :: (b -> c) -> (a -> b) -> a -> c -- Defined in GHC.Base
Эта нотация как-то связана с комбинаторной логикой, но я не в куре математических тонкостей.
Оператор просто принимает на вход две функции и передаёт выход второй на вход первой. Получается новая функция, которая принимает на вход то, что принимает на вход вторая функция. Для удобства можно было бы записать так:
(BInt . read)
Да, BInt — это один из конструкторов типа BCode. Это функция, которая принимает на вход Integer и возвращает BCode.
<$>
Это то же самое, что fmap. Принимает на вход чистую функцию и функцию с побочным зффектом. Сначала вычисляет функцию с побочным эффектом, берёт оттуда чистый результат, подаёт на вход чистой функции. Результат всего этого делает побочным.
getWrapped 'i' 'e' intP
Здесь происходит сам парсинг с побочным эффектом.
(:) -- оператор добавления элемента в начало списка
<$> <*> -- операторы из Control.Applicative, позволяют удобно комбинировать чистые функции и функции с эффектами.
<|> -- оператор выбора альтернатив парсера, такой же как в parsec.
Т.е. intP — это парсер, для которого валидными строками являются символ "-", а потом то, что парсится функцией getDigits, либо просто то, что парсится функцией
getDigits без минуса. Возвращает он всегда точно такую же строку, которую распарсил. getDigits — это одна или больше цифр, что понятно из кода ниже.
getWrapped 'i' 'e' intP
Это функция, которая делает из парсера intP новый парсер. Путём добавления в начало и в конец двух символов для парсинга.
-- | Get something wrapped in two Chars
getWrapped :: Char -> Char -> Get a -> Get a
getWrapped a b p = char a *> p <* char b
Операторы (*>) и (<*) я никогда раньше не использовал и не знал что такое. Берём hoogle www.haskell.org/hoogle/, вводим там (*>). Попадаем в документацию к модулю Control.Applicative:
(*>) :: f a -> f b -> f b
Sequence actions, discarding the value of the first argument.
(<*) :: f a -> f b -> f a
Sequence actions, discarding the value of the second argument.
Всё ясно, будем знать.
Итог: 20 секунд на понимание кода и 10 минут на этот текст. Какие недели, о чём вы?
Надеюсь, не стоит приводить примеры из c++, c#, python, perl, которые произведут точно такое же впечатление на первый взгляд?
После прочтения нескольких руководств и вхождения в тему большинство библиотек становятся поятными. И это мясо обычно не учат, а используют как справочник. А ещё чаще как справочник используют hoogle или hayoo и особо не запоминают какие функции и типы в каких модулях лежат.
Думал что этот мир сошёл с ума, раз люди пишут на этом и пишут это. Очень рад что многие разделяют отношение к с++ как к абсурду.
Тогда с++ не любил не со стороны питона и си шарпа, а со стороны простого Си. Да, и в своё время был профессиональным с++ программистом.
могильничекнебольшой проект.Проект сугубо прикладной.
У меня имеется также желание реализовать некоторые более грандиозные идеи, но пока нет времени. Например, дедуктивную субд с интерфейсом на даталоге, надмножестве sql.
Если так, то замечательно. А вот на монетизацию я бы особо не расчитывал.
Даже нет особого желания разбираться с тем, как он работает.
По теме: возможно, все минусующие не испытывают потребности в поиске, выборе и приобретении книг. Или их потребности полностью покрываются другими способами.
Возможно, поэтому проект не стал достаточно популярным.
Я так и не нашёл ни одной годной реализации, всё очень примитивно.
Выяснил, что SWI-Prolog это самая продвинутая реализация. Так вот это очень недоразвитый проект. Ничего практически полезного с ним сделать нельзя. Документация по интеграции с другими системами ужасная. Очень сложный сишный код, который периодически падает по непонятным причинам.
Например, code.google.com/p/pyswip/ — библиотека работы с swi-prolog из python. Есть аналогичная библиотека для хаскеля hackage.haskell.org/package/hswip. Попробуйте сделать с их помощью многопоточную программу. Чтобы с интерпретатором могли работать сразу несколько потоков. Это невозможно.
Я думаю что у пролога большое будущее. Но писать исполняемый код на нём большое извращение.
Пролог идеален только в качестве языка запроса к дедуктивным базам данных. В конце концов SQL это частный случай пролога. На прологе можно намного проще делать всякие outer join и выполнять рекурсивные запросы без использования хранимых процедур. Реально проще.
Осталось только написать такую дедуктивную СУБД.
Но главная проблема я так понимаю не в коде, а в обучении. Свежего человека отправляем на неделю или сколько ему нужно знакомиться с базовыми концепциями. В дальнейшем при встрече каждого непонятного смайлика опытный человек говорит ему куда копать, что читать и что чёрт возьми тут происходит.
Как быстро вольётся — сложный вопрос. Но есть же разные участки кода по сложности. Самые простые вещи, думаю, можно начать писать очень быстро.
Ключевой момент здесь — тип Get a. Что это такое, я не знаю, в этом модуле не определён. Нужно найти откуда он импортируется и понять что он точно делает. По коду он похож на монаду парсинга, такую как в parsec.
Сигнатура функции говорит, что в этом месте из какого-то потока токенов, может быть строки символов, парсится значение типа BCode.
Описание типа BCode есть в этом модуле.
Это бесточечная нотация www.haskell.org/haskellwiki/Pointfree.
Вот сигнатура оператора (.):
Эта нотация как-то связана с комбинаторной логикой, но я не в куре математических тонкостей.
Оператор просто принимает на вход две функции и передаёт выход второй на вход первой. Получается новая функция, которая принимает на вход то, что принимает на вход вторая функция. Для удобства можно было бы записать так:
Да, BInt — это один из конструкторов типа BCode. Это функция, которая принимает на вход Integer и возвращает BCode.
Это то же самое, что fmap. Принимает на вход чистую функцию и функцию с побочным зффектом. Сначала вычисляет функцию с побочным эффектом, берёт оттуда чистый результат, подаёт на вход чистой функции. Результат всего этого делает побочным.
Здесь происходит сам парсинг с побочным эффектом.
Т.е. intP — это парсер, для которого валидными строками являются символ "-", а потом то, что парсится функцией getDigits, либо просто то, что парсится функцией
getDigits без минуса. Возвращает он всегда точно такую же строку, которую распарсил. getDigits — это одна или больше цифр, что понятно из кода ниже.
Это функция, которая делает из парсера intP новый парсер. Путём добавления в начало и в конец двух символов для парсинга.
Операторы (*>) и (<*) я никогда раньше не использовал и не знал что такое. Берём hoogle www.haskell.org/hoogle/, вводим там (*>). Попадаем в документацию к модулю Control.Applicative:
Всё ясно, будем знать.
Итог: 20 секунд на понимание кода и 10 минут на этот текст. Какие недели, о чём вы?
Надеюсь, не стоит приводить примеры из c++, c#, python, perl, которые произведут точно такое же впечатление на первый взгляд?
После прочтения нескольких руководств и вхождения в тему большинство библиотек становятся поятными. И это мясо обычно не учат, а используют как справочник. А ещё чаще как справочник используют hoogle или hayoo и особо не запоминают какие функции и типы в каких модулях лежат.