Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
MakeevGA-Haskell-a4-shortcode_2014_05_31.doc
Скачиваний:
15
Добавлен:
19.01.2023
Размер:
1.79 Mб
Скачать

Пояснения и обозначения

Вот таким шрифтом обозначаются куски кода, имена функций и сигнатуры типа.

Вот таким образом оформлены замечания, дополнения и заметки на полях.

Демонстрация кунг-фу

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

qsort [] = []

qsort (x:xs) = qsort [y | y <- xs, y <= x]

++ [x] ++

qsort [y | y <- xs, y > x]

Вот бесконечный список чисел Фибоначчи:

fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

или так:

fibbs = 1 : 1 : next fibbs where

next (x:y:xs) = x + y : next (y:xs)

или так:

fibbbs = next 0 1 where

next x y = y : next y (x+y)

Вот простые числа:

primes = map head $ iterate sieve [2..] where

sieve (x:xs) = [y | y <-xs, y `mod` x /= 0]

или так:

primes = 2 :

filter (\x -> all (\p -> x `mod` p /= 0) $

takeWhile (\p -> p^2 <= x) primes)

[3..]

А вот создание идеально сбалансированного бинарного поискового дерева:

data Ord a => SearchTree a =

Empty | Branches a (SearchTree a) (SearchTree a)

deriving Show

putVal x Empty = Branches x Empty Empty

putVal x (Branches v l r)

| x > v = Branches v l (putVal x r)

| otherwise = Branches v (putVal x l) r

list2tree xs = foldl (flip putVal) Empty xs

height Empty = 0

height (Branches v l r) = max (height l) (height r) + 1

stepr (Branches v l@(Branches lv ll lr) r)

| height lr > height ll =

stepr (Branches v (stepl l) r)

| otherwise =

(Branches lv ll (Branches v lr r))

stepl (Branches v l r@(Branches rv rl rr))

| height rl > height rr =

stepl (Branches v l (stepr r))

| otherwise =

(Branches rv (Branches v l rl) rr)

balance Empty = Empty

balance t@(Branches v l r) =

balance' (Branches v (balance l) (balance r)) where

balance' t@(Branches v l r)

| height l - height r > 1 =

balance $ stepr (Branches v l r)

| height r - height l > 1 =

balance $ stepl (Branches v l r)

| otherwise = t

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

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