-
OverloadedLists -
- Since:
-
7.8.1
Включить синтаксис перегруженных списков (например, разаннования списков через класс
IsList).
GHC поддерживает перегрузку записи списков. Давайте вспомним запись для построения списков. В Haskell запись списков может быть использована следующими семью способами:
[] -- Empty list [x] -- x : [] [x,y,z] -- x : y : z : [] [x .. ] -- enumFrom x [x,y ..] -- enumFromThen x y [x .. y] -- enumFromTo x y [x,y .. z] -- enumFromThenTo x y z
Когда включена расширение OverloadedLists, вышеуказанные семь записей разанновываются следующим образом:
[] -- fromListN 0 [] [x] -- fromListN 1 (x : []) [x,y,z] -- fromListN 3 (x : y : z : []) [x .. ] -- fromList (enumFrom x) [x,y ..] -- fromList (enumFromThen x y) [x .. y] -- fromList (enumFromTo x y) [x,y .. z] -- fromList (enumFromThenTo x y z)
Это расширение позволяет программистам использовать запись списков для построения структур, таких как: Set, Map, IntMap, Vector, Text и Array. Следующий фрагмент кода предоставляет несколько примеров:
['0' .. '9'] :: Set Char
[1 .. 10] :: Vector Int
[("default",0), (k1,v1)] :: Map String Int
['a' .. 'z'] :: Text
Шаблоны списков также перегружены. При включении расширения OverloadedLists эти определения разанновываются следующим образом
f [] = ... -- f (toList -> []) = ... g [x,y,z] = ... -- g (toList -> [x,y,z]) = ...
(Здесь мы используем синтаксис шаблонов вида для перевода, см. Шаблоны вида.)
6.2.9.1. Класс IsList
В вышеприведённых разаннованиях функции toList, fromList и fromListN — всё это методы класса IsList, который сам экспортируется из модуля GHC.Exts. Класс типа определяется следующим образом:
class IsList l where type Item l fromList :: [Item l] -> l toList :: l -> [Item l] fromListN :: Int -> [Item l] -> l fromListN _ = fromList
Класс IsList и его методы предназначены для использования совместно с расширением OverloadedLists.
- Функция типа
Itemвозвращает тип элементов структурыl. - Функция
fromListстроит структуруlиз данного спискаItem l. - Функция
fromListNпринимает длину входного списка как подсказку. Её поведение должно быть эквивалентноfromList. Подсказка может быть использована для более эффективного построения структурыlпо сравнению сfromList. Если указанная подсказка не равна длине входного списка, поведениеfromListNне определено. - Функция
toListдолжна быть обратной кfromList.
Совершенно допустимо объявлять новые экземпляры IsList, чтобы запись списков стала полезной для совершенно новых типов данных. Вот несколько примеров экземпляров:
instance IsList [a] where type Item [a] = a fromList = id toList = id instance (Ord a) => IsList (Set a) where type Item (Set a) = a fromList = Set.fromList toList = Set.toList instance (Ord k) => IsList (Map k v) where type Item (Map k v) = (k,v) fromList = Map.fromList toList = Map.toList instance IsList (IntMap v) where type Item (IntMap v) = (Int,v) fromList = IntMap.fromList toList = IntMap.toList instance IsList Text where type Item Text = Char fromList = Text.pack toList = Text.unpack instance IsList (Vector a) where type Item (Vector a) = a fromList = Vector.fromList fromListN = Vector.fromListN toList = Vector.toList
Однако пользователи не должны предоставлять никаких экземпляров, которые перекрываются с первым экземпляром выше. Иными словами, fromList и toList, когда используются со списками, всегда должны быть тождественной функцией. Например, следующий экземпляр запрещён:
instance {-# OVERLAPPING #-} IsList [Int] where
type Item [Int] = Int
fromList = reverse
toList = reverse
6.2.9.2. Переопределяемый синтаксис
При разанновании записи списков с помощью OverloadedLists GHC использует методы fromList (и т.д.) из модуля GHC.Exts. Вам не нужно импортировать GHC.Exts для этого.
Однако, если вы используете RebindableSyntax, GHC вместо этого использует то, что находится в области видимости с именами toList, fromList и fromListN . То есть эти функции переопределяемы; см. Переопределяемый синтаксис и неявный импорт Prelude.
6.2.9.3. По умолчанию
В настоящее время для класса IsList нет правил по умолчанию. Хотя это возможно, не было уделено много внимания тому, как указать смысл таких объявлений по умолчанию, как:
default ([a])
6.2.9.4. Предположения о будущем
Текущую реализацию расширения OverloadedLists можно улучшить, обработав списки, содержащие только литералы, особым способом. Более конкретно, компилятор мог бы статически выделять такие списки, используя компактное представление, и позволять экземплярам IsList использовать компактное представление. Обладая этой возможностью, расширение OverloadedLists будет в хорошем положении, чтобы поглотить расширение OverloadedStrings (в настоящее время, как специальный случай, строковые литералы извлекают выгоду от статического выделения компактного представления).