Кортежи
Кортежем называется упорядоченный набор элементов фиксированной длины. При этом тип элементов может быть произвольный. Первый элемент кортежа может относиться к одному типу, второй к другому, третий элемент к третьему или опять к первому типу.Синтаксис
В Haskell кортеж заключается в круглые скобки, а элементы разделяются запятыми. Миксфиксный стиль:
Альтернативный синтаксис (префиксный стиль конструирования):
Зададим точки на плоскости парами типа (Double, Double). Функцию dist, возвращает расстояние между двумя точками, передаваемыми ей в качестве аргументов.
Можно реализовать 9 разных всегда завершающихся функций с типом a -> (a,b) -> a -> (b,a,a).
foo :: a -> (a,b) -> a -> (b,a,a)
Для списков типа Char имеется стандартный синоним String, который может использоваться всюду, где используется список типа Char. Вместо списка типа Char можно писать String.
Операция добавления элемента в голову списка:
Оператор добавления элемента в голову списка это оператор двоеточие. Левым его аргументом служит элемент списка, а правым аргументом целый список.
Операция конкатенации двух списков:
Оператор конкатенации списков это два оператора плюс идущих подряд. С помощью этого оператора можно из двух списков одного и того же типа собрать список того же самого типа, но более длинный.
Операторы (:) и (++) имеют одинаковую ассоциативность и приоритет.
Prelude> (2,True) (2,True) Prelude> (2,True,'c') (2,True,'c')
Альтернативный синтаксис (префиксный стиль конструирования):
Prelude> (True,3) (True,3) Prelude> (,) True 3 (True,3) Prelude> (,,) True 3 'c' (True,3,'c')
Двухэлементные кортежи
Для двухэлементных кортежей есть полезные вспомогательные функции.Prelude> fst (2,True) 2 Prelude> snd (2,True) True
Зададим точки на плоскости парами типа (Double, Double). Функцию dist, возвращает расстояние между двумя точками, передаваемыми ей в качестве аргументов.
dist :: (Double, Double) -> (Double, Double) -> Double dist p1 p2 = sqrt $ (fst p1 - fst p2) * (fst p1 - fst p2) + (snd p1 - snd p2) * (snd p1 - snd p2)
Тип кортежа
Тип кортежа устроен точно также как его значение.Prelude> :t ('x',True) ('x',True) :: (Char, Bool) Prelude> :t ('x',True,'s') ('x',True,'s') :: (Char, Bool, Char)
Единичный кортеж
В Haskell нет единичного кортежа. Выражение (3) представляет собой не кортеж, а просто тройку заключенную в скобки, которые в данном случае рассматриваются как лишний декоративный элемент возможно связанный с группировкой.Prelude> (3) 3
Пустой кортеж
В Haskell есть пустой кортеж. Тип этого выражения совпадает со значением этого выражения. Хотя здесь один и тот же символ используется и для типа и для значения, тем не менее это не страшно потому что пространство имен для типов и пространство имен для выражений никогда не пересекаются.Prelude> () () Prelude> :t () () :: ()
Полиморфизм кортежей
Кортежи тоже полиморфны. Более того степень полиморфизма кортежей даже выше чем степень полиморфизма списков.Prelude> :t (,) (,) :: a -> b -> (a, b) Prelude> :t (,,) (,,) :: a -> b -> c -> (a, b, c) Prelude> :t (,) True 'c' (,) True 'c' :: (Bool, Char) Prelude> let dup x = (x,x) Prelude> :t dup dup :: t -> (t, t) Prelude> :t fst fst :: (a, b) -> a Prelude> :t snd snd :: (a, b) -> b
Можно реализовать 9 разных всегда завершающихся функций с типом a -> (a,b) -> a -> (b,a,a).
foo :: a -> (a,b) -> a -> (b,a,a)
- let foo p1 p2 p3 = (snd p2, p1, p1)
- let foo p1 p2 p3 = (snd p2, p1, fst p2)
- let foo p1 p2 p3 = (snd p2, p1, p3)
- let foo p1 p2 p3 = (snd p2, fst p2, p1)
- let foo p1 p2 p3 = (snd p2, fst p2, fst p2)
- let foo p1 p2 p3 = (snd p2, fst p2, p3)
- let foo p1 p2 p3 = (snd p2, p3, p1)
- let foo p1 p2 p3 = (snd p2, p3, fst p2)
- let foo p1 p2 p3 = (snd p2, p3, p3)
Списки
Списки как и кортежи представляют собой контейнерный тип. Однако имеются два существенных отличия:- списки гомогенные (все элементы списка принадлежат к одному типу) в отличие от гетерогенных кортежей;
- длина списка не фиксирована и неизвестна компилятору в отличие от кортежа.
Синтаксис
Элементы списка перечисляются через запятую, а сам список заключается в квадратный скобки.Prelude> [1,2,3] [1,2,3] Prelude> [False,True] [False,True]
Тип списков
Поскольку списки гомогенные, то их тип не зависит от их длины. Также как и в кортежах, тип повторяет структуру значения. Квадратные скобки указывают на то что это список.Prelude> :t [False,True] [False,True] :: [Bool]
Списки типа Char
Для списков типа Char имеется специальный синтаксис.Prelude> ['H','i'] "Hi" Prelude> :t ['H','i'] ['H','i'] :: [Char] Prelude> :t "Hi" "Hi" :: [Char] Prelude> "Hi" :: String "Hi"
Для списков типа Char имеется стандартный синоним String, который может использоваться всюду, где используется список типа Char. Вместо списка типа Char можно писать String.
Операции над списками
Операция добавления элемента в голову списка:Prelude> let str = 'H' : "ello" Prelude> str "Hello"
Операция конкатенации двух списков:
Prelude> str ++ ", world!" "Hello, world!"
Операторы (:) и (++) имеют одинаковую ассоциативность и приоритет.
Prelude> :info : data [] a = ... | a : [a] -- Defined in ‘GHC.Types’ infixr 5 : data [] a = ... | a : [a] -- Defined in ‘GHC.Types’ infixr 5 : Prelude> :info ++ (++) :: [a] -> [a] -> [a] -- Defined in ‘GHC.Base’ infixr 5 ++
Prelude> 1 : [2,3] ++ [4,5,6] [1,2,3,4,5,6] Prelude> [1,2] ++ 3 : [4,5,6] [1,2,3,4,5,6] Prelude> [1,2] ++ (:) 3 [4,5,6] [1,2,3,4,5,6] Prelude> (:) 1 ((++) [2,3] [4,5,6]) [1,2,3,4,5,6]
Полиморфизм списков
Встроенные структуры такие как списки и кортежи тоже параметрически полиморфны. Списки имеют полиморфное поведение, в качестве элементов списка можно использовать любой тип. Списки полиморфны по типу элементов, которые хранятся в этом списке. Этот же полиморфизм присутствует и в стандартных функциях над списками.
Prelude> :t [True,False] [True,False] :: [Bool] Prelude> :t "Hello" "Hello" :: [Char] Prelude> :t [] [] :: [t] Prelude> :t (++) (++) :: [a] -> [a] -> [a] Prelude> :t (:) (:) :: a -> [a] -> [a]
Комментариев нет:
Отправить комментарий