+
+
+
+Функциональное программирование
+
+
+
+
+Функциональное программирование:
+
+функции – это тоже данные.
+
+Int -> Bool
(функция) – ровно такие же данные как и Int
. Их также можно складывать в структуры, передавать как аргументы и т. п.
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+
+
+
+
+
+
+
+ static <T> T f(T x)
+ static <T> T g(T x)
+ |
+
+ f :: a -> a
+ g :: a -> a
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+
+
+
+
+
+h = f . g
+h x == f (g x)
+
+
+
+
+
+моноид
+
+
+
+
+Моноид
+Бинарная асоциативная операция
+(.) :: (a -> a) -> (a -> a) -> (a -> a)
+Нейтральный элемент
+
+
+
+
+
+Чисто функционаьлный
+Все что функция может сделать – посмотреть на свои аргументы это вернуть значение.
+
+
+
+
+Referential transparency
+(Любую константу можно заменить на само значение)
+int x = 8;
+int y = x++;
+System.out.println(y + " might be the same as " + y);
+int x = 8;
+System.out.println(x++ + " might be the same as " + x++);
+
+
+
+
+Нет переменных, циклов и условных переходов
+Зато есть константы и нормальная рекурсия (А переходов вообще нет)
+
+
+
+Очень ленивый
+xs = [4, 1, 3, 2]
+xs' = sort xs
+print xs
+
+
xs'
не нужен чтобы распечатать xs
, поэтому сортироваться ничто не будет. (Зачем делать то, что можно не делать)
+
+
+
+
+Если хотите быстро и просто потыкаться, тут есть интерктивная штука:
+haskell.org
+
+
+
+
+
+add2 :: Int -> Int
+add2 x = x + 2
+Все функции и константы всегда обозначаются словами с маленькой буквы без пробелов.
+(Константы это просто функции с нулем аргументов.)
+
+
+
+Pattern mathcing
+fixBuz :: Int -> String
+divide8 3 = "Fiz"
+divide8 5 = "Buz"
+divide8 15 = "FizBuz"
+divide8 _ = "Some other number"
+Так матчить можно произвольные структуры произвольного уровня вложенности.
+_
– специальное название константы, которое говорит что вам все равно что в ней лежит.
+
+
+
+
+
+data Foo = Bar
+foo :: Bar
+foo = Bar
+Foo
– тип структуры. Bar
– конструктор структуры.
+Тут у Foo
всего одно значение Bar
.
+
+
+
+Произведение типов
+(обычные поля структур)
+
+data PersonType = Person String Int
+vasya :: PersonType
+vasya = Person "Vasya" 8
+-- тип можно не укзывать
+petya = Person "Petya" 5
+getName :: PersonType -> String
+getName (Person name _) = name
+greetPerson :: PersonType -> String
+greetPerson p = "Hello, " ++ getName p
+greetPerson petya
+-- "Hello, Petya"
+
+
+
+Еще немного функций
+greetPerson :: PersonType -> String
+greetPerson p = "Hello, " ++ getName p
+greetPerson :: PersonType -> String
+greetPerson p = "Hello, " ++ name
+ where
+ name = getName p
+greetPerson :: PersonType -> String
+greetPerson p = "Hello, " ++ name
+ where
+ getName' (Person name _) = name
+ name = getName' p
+
+
+
+data PersonType = Person String Int
+
+getName :: PersonType -> String
+getName (Person name _) = name
+greetName :: String -> String
+greetName name = "Hello, " ++ name
+greetPerson :: PersonType -> String
+greetPerson p = greetName (getName p)
+greetPerson :: PersonType -> String
+greetPerson = greetName . getName
+greetPerson petya
+-- "Hello, Petya"
+(greetName . getName) petya
+-- "Hello, Petya"
+
+
+
+Суммы типов
+
+
+x :: Bool
+x = True
+y = False
+ifThenElse :: (Bool, a, a) -> a
+ifThenElse (True, a, _) = a
+ifThenElse (False, _, b) = b
+ifThenElse (True, "Hello", "World")
+-- "Hello"
+ifThenElse (False, "Hello", "World")
+-- "World"
+
+
+
+data CircleType = Circle Double Double Double
+data RectangleType = Rectangle Double Double Double Double
+data Shape =
+ CircleShape CircleType | RectangleShape RectangleType
+surface :: Shape -> Double
+surface (CircleShape (Circle _ _ r)) =
+ pi * r ^ 2
+surface (RectangleShape (Rectangle x1 y1 x2 y2)) =
+ (abs (x2 - x1)) * (abs (y2 - y1))
+shape = CircleShape (Circle 0 0 2)
+surface shape
+-- 12.566370614359172
+otherShape = RectangleShape (Rectangle 1 2 3 4)
+surface otherShape
+-- 4.0
+
+
+
+
+Лямбда-выражения
+
+
+
+λ – \
(λ печатать тяжело)
+foo :: (Int -> Int) -> Int
+
+
+
+
+
+Давайте придумаем синтаксис для функции нескольких аргументов!
+
+
+
+x, y :: Int
+x = 42
+y = 69
+xPlusY :: Int
+xPlusY = add x y
+Применение функции – лево-ассоциативно
+
+
+
+add :: Int -> (Int -> Int)
+
+
+
+add :: Int -> (Int -> Int)
+Тип ->
– право-ассоциативный
+
+
+
+
+
+
+Любая функция берет строго один аргумент.
+Функция нескольких аргументов все равно берет строго одтн аргумент и возвращает функцию, которая берет следйющий.
+(И из-за того, что применение функции лево-ассоциативно, вызов таких не трубует особого синтаксиса.)
+
+
+
+Currying
+add :: Int -> Int -> Int
+add a b = a + b
+
+add :: Int -> (Int -> Int)
+
+
+
+
+
+Funny fact
+Оператор (например +
) – функция, название которой не содержит буквы и цифры.
+
+
+
+
+
+Funny fact 2
+Оператор можно превратить в функцию, окружив его скобками.
+add :: Int -> Int -> Int
+add x y = x + y
+
+
+
+
+
+Funny fact 3
+Функцию можно превратить в оператор, окружив ее обратными кавычками.
+add :: Int -> Int -> Int
+add x y = x + y
+
+
+
+
+
+
+Односвязный список
+data IntList = Cons Int IntList | Nil
+Cons :: Int -> IntList -> IntList
+Nil :: IntList
+nums :: IntList
+nums = 1 `Cons` (2 `Cons` (3 `Cons` Nil))
+
+sum (Cons x xs) = x + sum xs
+sum Nil = 0
+sum (Cons x xs) = x + sum xs
+
+
+
+
+take :: Int -> IntList -> IntList
+take _ Nil = Nil
+take 0 _ = Nil
+take n (Cons x xs) = Cons x (take (n - 1) xs)
+nums :: IntList
+nums = 1 `Cons` (2 `Cons` (3 `Cons` Nil))
+take 2 nums
+-- Cons 1 (Cons 2 Nil)
+take 1029 nums
+-- Cons 1 (Cons 2 (Cons 3 Nil))
+take 0 nums
+-- Nil
+
+
+
+
+repeat n = Cons n (repeat n)
+repeat 8
+-- Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (Cons 8 (...
+(take 3 . repeat) 8
+-- Cons 8 (Cons 8 (Cons 8 Nil))
+(sum . take 3 . repeat) 8
+-- 24
+
+
+
+
+
+
+Наша самодеятельность
+ |
+
+В стандартной библиотеке
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+ |
+
+
+
+
+ |
+
+
+
+ |
+
+
+
+
+
+repeat
, sum
и take
тоже есть в стандартной библиотеке.
+
+
+
+
+quicksort :: [Int] -> [Int]
+quicksort (x:xs) =
+ quicksort smaller ++ [x] ++ quicksort larger
+ where
+ smaller = filter (< x) xs
+ larger = filter (>= x) xs
+
+
+
+filter :: (Bool -> Int) -> [Int] -> [Int]
+filter f (x:xs) =
+ if f x
+ then filter f xs
+ else x:(filter f xs)
+filter _ [] = []
+filter f (x:xs) =
+ if f x
+ then filter f xs
+ else x:(filter f xs)
+
+
+
+quicksort :: [Int] -> [Int]
+quicksort (x:xs) =
+ quicksort smaller ++ [x] ++ quicksort larger
+ where
+ smaller = filter (< x) xs
+ larger = filter (>= x) xs
+ filter _ [] = []
+ filter f (x:xs) =
+ if f x
+ then filter f xs
+ else x:(filter f xs)
+
+
+
+quicksort :: [Int] -> [Int]
+quicksort [] = []
+quicksort (x:xs) =
+ quicksort smaller ++ [x] ++ quicksort larger
+ where
+ smaller = filter (< x) xs
+ larger = filter (>= x) xs
+ filter _ [] = []
+ filter f (x:xs) =
+ if f x
+ then filter f xs
+ else x:(filter f xs)
+quicksort [2, 1, 3, 4]
+-- [1, 2, 3, 4]
+
+
+
+filter
тоже есть в стандартной библиотеке.
+
+
+Где и как смотреть “стандартную библиотеку”
+
+
+
+
+Hackage
+(Там вам нужен только пакет base
. Ссылка ведет прямо на него.) Еще если там нажать s
, то будет поиск.
+Hoogle
+Это поиск по типам. Например: Int -> [Int] -> [Int]
(Тут вам опять же нужен только пакет base
. Нужно чтобы справа было "package:base".)
+
+
+