|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
f :: a -> a
g :: a -> a
f (g x)
(f . g) x == f (g x)
h = f . g
h x == f (g x)
f :: a -> a
g :: a -> a
h :: a -> a
h = f . g
Бинарная асоциативная операция
(.) :: (a -> a) -> (a -> a) -> (a -> a)
Нейтральный элемент
id :: a -> a
id x = x
Все что функция может сделать -- посмотреть на свои аргументы это вернуть значение.
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.orgadd2 :: Int -> Int
add2 x = x + 2
Все функции и константы всегда обозначаются словами с маленькой буквы без пробелов.
(Константы это просто функции с нулем аргументов.)
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"
data Bool = False | True
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
add8 :: Int -> Int
add8 x = x + 8
add8 = \x -> x + 8
λ -- `\` (λ печатать тяжело)
foo :: (Int -> Int) -> Int
foo add8
foo (\x -> x + 8)
x, y :: Int
x = 42
y = 69
xPlusY :: Int
xPlusY = add x y
Применение функции -- лево-ассоциативно
xPlusY = (add x) y
xPlusY = f y
f = add x
f :: Int -> Int
add :: Int -> (Int -> Int)
add :: Int -> (Int -> Int)
Тип `->` -- право-ассоциативный
add :: Int -> Int -> Int
add a b = a + b
add = \a b -> a + b
Любая функция берет строго один аргумент.
Функция нескольких аргументов все равно берет строго одтн аргумент и возвращает функцию, которая берет следйющий.
(И из-за того, что применение функции лево-ассоциативно, вызов таких не трубует особого синтаксиса.)
add :: Int -> Int -> Int
add a b = a + b
add8 :: Int -> Int
add :: Int -> (Int -> Int)
add8 = add 8
add8 3
-- 11
Оператор (например `+`) -- функция, название которой не содержит буквы и цифры.
x +&+ y = x + y
8 +&+ 9
-- 17
Оператор можно превратить в функцию, окружив его скобками.
add :: Int -> Int -> Int
add x y = x + y
add = (+&+)
add = (+)
Функцию можно превратить в оператор, окружив ее обратными кавычками.
add :: Int -> Int -> Int
add x y = x + y
add 8 9
-- 17
8 `add` 9
-- 17
data IntList = Cons Int IntList | Nil
nums :: IntList
nums = 1 `Cons` (2 `Cons` (3 `Cons` Nil))
sum :: IntList -> Int
sum (Cons x xs) = x + sum xs
sum Nil = 0
sum (Cons x xs) = x + sum xs
sum nums
-- 6
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 :: Int -> IntList
repeat n = 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` тоже есть в стандартной библиотеке.