У вас проблема с вашим DNS. Я уверен, что если вы сделаете:
$ ping deb.debian.org
Вы также получите ошибку.
Я бы порекомендовал вам прочитать это
То, как мне это показалось, и то, что я считаю верным после того, как я работал над Хаскеллом в течение месяца, является тот факт, что функциональное программирование крутит ваш мозг интересными способами: вынуждает вас думать о знакомых проблемах по-разному: вместо циклов, мыслей в картах, сгибах и фильтрах и т. д. В общем, если у вас есть более одного взгляда на проблему, это дает вам больше возможностей для рассуждения об этой проблеме, и при необходимости меняйте точки зрения.
Другая действительно интересная вещь в Haskell - это система типов. Он строго типизирован, но механизм вывода типов напоминает программу Python, которая волшебным образом сообщает вам, когда вы совершили глупую ошибку, связанную с типом. Сообщения об ошибках Хаскеля в этом отношении несколько отсутствуют,
Передать противоположный вид: бесполезный формальный математический смысл. Это обрабатывает несколько вычислительных конструкций очень хорошо; сопоставление с образцом отправка найдена в Haskell, SML и OCaml особенно удобен. Неудивительно, что он обрабатывает некоторые другие общие и весьма желательные конструкции в лучшем случае неловко, но они объясняют эти сценарии далеко, сказав, что вы ошибаетесь, вы на самом деле не хочу их. Вы знаете, такие вещи, как, о, установка переменных.
Haskell стоит изучить, но у него есть свои слабые стороны.
он не имеет циклических конструкций. не многие языки имеют эту черту.
Если вы можете обернуть голову вокруг системы типов в Хаскеле, я думаю, что это само по себе довольно большое достижение.
Я согласен с другими, что увидеть несколько небольших примеров - не лучший способ показать Хаскель. Но я все равно дам немного. Вот молниеносное решение задач проекта Эйлера 18 и 67 , в котором вас попросят найти путь с максимальной суммой от основания до вершины треугольника:
bottomUp :: (Ord a, Num a) => [[a]] -> a
bottomUp = head . bu
where bu [bottom] = bottom
bu (row : base) = merge row $ bu base
merge [] [_] = []
merge (x:xs) (y1:y2:ys) = x + max y1 y2 : merge xs (y2:ys)
Вот полная, многократно используемая реализация алгоритма BubbleSearch Леша и Митценмахера. Я использовал его для упаковки больших медиа-файлов для архивного хранения на DVD без потерь:
data BubbleResult i o = BubbleResult { bestResult :: o
, result :: o
, leftoverRandoms :: [Double]
}
bubbleSearch :: (Ord result) =>
([a] -> result) -> -- greedy search algorithm
Double -> -- probability
[a] -> -- list of items to be searched
[Double] -> -- list of random numbers
[BubbleResult a result] -- monotone list of results
bubbleSearch search p startOrder rs = bubble startOrder rs
where bubble order rs = BubbleResult answer answer rs : walk tries
where answer = search order
tries = perturbations p order rs
walk ((order, rs) : rest) =
if result > answer then bubble order rs
else BubbleResult answer result rs : walk rest
where result = search order
perturbations :: Double -> [a] -> [Double] -> [([a], [Double])]
perturbations p xs rs = xr' : perturbations p xs (snd xr')
where xr' = perturb xs rs
perturb :: [a] -> [Double] -> ([a], [Double])
perturb xs rs = shift_all p [] xs rs
shift_all p new' [] rs = (reverse new', rs)
shift_all p new' old rs = shift_one new' old rs (shift_all p)
where shift_one :: [a] -> [a] -> [Double] -> ([a]->[a]->[Double]->b) -> b
shift_one new' xs rs k = shift new' [] xs rs
where shift new' prev' [x] rs = k (x:new') (reverse prev') rs
shift new' prev' (x:xs) (r:rs)
| r <= p = k (x:new') (prev' `revApp` xs) rs
| otherwise = shift new' (x:prev') xs rs
revApp xs ys = foldl (flip (:)) ys xs
Я уверен, что этот код выглядит как случайный бред. Но если вы прочитаете запись в блоге Митценмахера и поймете алгоритм, вы будете удивлены тем, что можно упаковать алгоритм в код, ничего не сказав о том, что вы ищете.
Приведя несколько примеров, о которых вы просили, я скажу, что лучший способ начать ценить Haskell - это прочитать статью, которая дала мне идеи, необходимые для написания DVD-упаковщика: Почему функциональное программирование имеет значение Джон Хьюз. Документ фактически предшествует Хаскеллу, но он блестяще объясняет некоторые идеи, которые делают людей такими, как Хаскелл.
Одна вещь, которую я нахожу очень интересной при работе с алгоритмами или математическими проблемами, - это ленивая оценка вычислений, присущая Haskell, которая возможна только из-за ее строгой функциональной природы.
Например, если вы Если вы хотите вычислить все простые числа, вы можете использовать
primes = sieve [2..]
where sieve (p:xs) = p : sieve [x | x<-xs, x `mod` p /= 0]
, и в результате вы получите бесконечный список. Но Haskell оценит его слева направо, поэтому, если вы не попытаетесь сделать что-то, что требует полного списка, вы все равно можете использовать его без зависания программы в бесконечности, например:
foo = sum $ takeWhile (<100) primes
, который суммирует все простых чисел меньше 100. Это хорошо по нескольким причинам. Прежде всего, мне нужно написать только одну простую функцию, которая генерирует все простые числа, а затем я почти готов работать с простыми числами. В объектно-ориентированном языке программирования Мне понадобится какой-то способ сообщить функции, сколько простых чисел она должна вычислить перед возвратом, или эмулировать поведение бесконечного списка с объектом. Другое дело, что в общем случае вы заканчиваете тем, что пишете код, который выражает то, что вы хотите вычислить, а не в каком порядке оценивать вещи - вместо этого компилятор делает это за вас.
На самом деле это полезно не только для бесконечных списков он привыкает без вашего ведома, когда нет необходимости оценивать больше, чем необходимо.
Интересный пример, который вы можете посмотреть на: http://en.literateprograms.org/Quicksort_ (Haskell)
Интересно посмотреть на реализацию на разных языках.
Что делает Haskell таким интересным, наряду с другими функциональными языками, так это Дело в том, что вы должны думать по-другому о том, как программировать. Например, вы, как правило, не будете использовать циклы for или while, но будете использовать рекурсию.
Как упоминалось выше, Haskell и другие функциональные языки превосходно подходят для параллельной обработки и написания приложений для работы на многоядерных процессорах.
Программная транзакционная память - это довольно крутой способ борьбы с параллелизмом. Это гораздо более гибко, чем передача сообщений, и не подвержено взаимной блокировке, как мьютексы. Реализация STM в GHC считается одной из лучших.
Part of the fuss is that purity and static typing enable for parallelism combined with aggressive optimisations. Parallel languages are hot now with multicore being a bit disruptive.
Haskell gives you more options for parallelism than pretty much any general purpose language, along with a fast, native code compiler. There is really no competition with this kind of support for parallel styles:
So if you care about making your multicore work, Haskell has something to say. A great place to start is with Simon Peyton Jones' tutorial on parallel and concurrent programming in Haskell.
Что на самом деле отличает Haskell, так это усилия, прилагаемые им при разработке функционального программирования. Вы можете программировать в функциональном стиле практически на любом языке, но от этого слишком легко отказаться при первом удобстве. Haskell не позволяет вам отказаться от функционального программирования, поэтому вы должны довести его до логического завершения, которое является конечной программой, о которой легче рассуждать, и обходит целый класс самых сложных типов ошибок.
Когда оно приходит При написании программы для использования в реальном мире вам может показаться, что на Haskell не хватает практического подхода, но ваше окончательное решение будет лучше, если вы знаете Haskell с самого начала. Я определенно еще не там, но до сих пор изучение Хаскелла было намного более поучительным, чем, скажем, Лисп учился в колледже.
Вы как бы задаете неправильный вопрос.
Хаскель - это не язык, где вы смотрите на несколько интересных примеров и говорите: «Ага, теперь я вижу, , это , что делает его хорошим!»
Это больше похоже на то, что у нас есть все эти другие языки программирования, и все они более или менее похожи, а затем есть Haskell, который совершенно другой и дурацкий, что совершенно удивительно, как только вы привыкаете к дурачеству. Но проблема в том, что для того, чтобы привыкнуть к дурачеству, требуется немало времени. Вещи, которые отличают Haskell от почти любого другого даже полу-мейнстримного языка:
а также некоторые другие аспекты, которые отличаются от многих основных языков (но разделяются некоторыми):
Как ответили некоторые другие авторы, сочетание всех этих особенностей означает, что вы думаете о программировании совершенно по-другому. И поэтому трудно придумать пример (или набор примеров), который адекватно сообщает об этом Joe-mainstream-programmer. Это опытная вещь. (Чтобы провести аналогию, я могу показать вам фотографии моей поездки в Китай в 1970 году, но после просмотра фотографий вы все равно выиграли » Не знаю, каково это было жить там в то время. Точно так же я могу показать вам «быструю сортировку» Haskell, но вы все равно не будете знать, что значит быть Haskeller.)
Я не могу дать Например, я парень из OCaml, но когда я нахожусь в такой ситуации, как вы, любопытство просто берет верх, и мне нужно скачать компилятор / интерпретатор и попробовать. Скорее всего, вы узнаете намного больше о сильных и слабых сторонах данного функционального языка.
Я согласен с теми, кто сказал, что функциональное программирование заставляет ваш мозг видеть программирование под другим углом. Я использовал его только как любитель, но я думаю, что это коренным образом изменило мой подход к проблеме. Я не думаю, что был бы так же эффективен с LINQ, если бы не познакомился с Haskell (и не использовал генераторы и списки в Python).
Последний год я изучал Haskell и писал на нем достаточно большой и сложный проект. (Проект представляет собой автоматическую систему торговли опционами, и все, от торговых алгоритмов до анализа и обработки низкоуровневых высокоскоростных потоков рыночных данных, выполняется на Haskell.) Он значительно более краток и проще для понимания (для тех, у кого есть соответствующий фон), чем версия Java, а также чрезвычайно надежный.
Возможно, самой большой победой для меня стала возможность модулировать поток управления через такие вещи, как моноиды, монады и так далее. Очень простой пример - моноид Ordering; в таком выражении, как
c1 `mappend` c2 `mappend` c3
, где c1
и так далее, return LT
, EQ
или GT
, c1
, возвращающий EQ
, вызывает продолжение выражения с вычислением c2
; если c2
возвращает LT
или GT
, это значение целого, а c3
не оценивается. Подобные вещи становятся значительно более изощренными и сложными в таких вещах, как генераторы монадических сообщений и парсеры, где я могу переносить различные типы состояний, иметь различные условия прерывания или, возможно, захочу решить для любого конкретного вызова, действительно ли означает прерывание. «без дальнейшей обработки» или означает «вернуть ошибку в конце, но продолжить обработку, чтобы собрать дальнейшие сообщения об ошибках».
Это все, что требуется некоторое время и, вероятно, довольно много усилий, чтобы изучить, и поэтому может быть трудно привести убедительные аргументы в пользу этого для тех, кто еще не знаком с этими методами. Я думаю, что учебник Все о монадах дает довольно впечатляющую демонстрацию одного аспекта этого, но я не ожидал, что кто-то, не знакомый с материалом, уже «поймет» это с первого или даже третье, внимательное прочтение.
В любом случае, в Haskell есть много других хороших вещей, но это главный вопрос, о котором я не замечаю упоминания так часто, вероятно, потому, что он довольно сложный.
Это пример , который убедил меня выучить Haskell (и я рад, что я это сделал).
-- program to copy a file --
import System.Environment
main = do
--read command-line arguments
[file1, file2] <- getArgs
--copy file contents
str <- readFile file1
writeFile file2 str
Хорошо, это короткая, читаемая программа. В этом смысле это лучше, чем программа на C. Но чем это так отличается от (скажем) программы Python с очень похожей структурой?
Ответ - ленивая оценка. В большинстве языков (даже в некоторых функциональных) программа, имеющая структуру, подобную приведенной выше, приведет к тому, что весь файл будет загружен в память, а затем снова записан под новым именем.
Haskell «ленив». Он не вычисляет вещи до тех пор, пока это не нужно, и, соответственно, не вычисляет вещи, которые ему никогда не нужны. Например, если бы вы удалили строку writeFile
, Haskell вообще не стал бы читать что-либо из файла.
Как бы то ни было, Haskell понимает, что writeFile
зависит от readFile
, и поэтому может оптимизировать этот путь данных.
Хотя результаты зависят от компилятора, при запуске вышеуказанной программы обычно происходит следующее: программа считывает блок (скажем, 8 КБ) первого файла, затем записывает его во второй файл, затем читает другой блок. из первого файла и записывает его во второй файл и так далее. (Попробуйте запустить на нем strace
!)
... что очень похоже на то, что делает эффективная реализация копии файла на языке C.
Итак, Haskell позволяет писать компактные, читаемые программы. - часто без ущерба для производительности.
Еще я должен добавить, что Haskell просто затрудняет написание программ с ошибками. Потрясающая система шрифтов, отсутствие побочных эффектов, и, конечно же, компактность кода Haskell уменьшает количество ошибок по крайней мере по трем причинам:
Лучший дизайн программы. Снижение сложности приводит к меньшему количеству логических ошибок.
Компактный код. Меньше строк с описанием ошибок.
Ошибки компиляции. Множество ошибок, просто недопустимы в Haskell .
Haskell не для всех. Но всем стоит попробовать.
Я считаю что для некоторых задач я невероятно продуктивен с Haskell.
Причина в лаконичном синтаксисе и простоте тестирования.
Вот как выглядит синтаксис объявления функции:
foo a = a + 5
Это самый простой способ определения функции, который я могу придумать.
Если я напишу обратный
inverseFoo a = a - 5
, я могу проверить, является ли он обратным для любого случайного ввода, написав
prop_IsInverse :: Double -> Bool
prop_IsInverse a = a == (inverseFoo $ foo a)
И вызов из командной строки
jonny @ ubuntu: runhaskell quickCheck + names fooFileName.hs
Что проверит, что все свойства в моем файле сохранены , путем случайного тестирования входных данных сто раз так.
Я не думаю, что Haskell - идеальный язык для всего, но когда дело доходит до написания небольших функций и тестирования, я не видел ничего лучше. Если ваше программирование имеет математический компонент, это очень важно.
Для меня привлекательность Haskell - это обещание гарантированной корректности компилятора. Даже если это для чистых частей кода.
Я написал много кода научного моделирования и много раз задавался вопросом , так , была ли ошибка в моих предыдущих кодах, которая могла бы сделать недействительной большую часть текущей работы.