Spec-Zone.ru › Haskell 9

6.2.9. Перегруженные списки

OverloadedLists
Начиная с:

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 (в настоящее время строковые литералы уже выигрывают от статически размещаемого компактного представления).

© 2002–2007 The University Court of the University of Glasgow. All rights reserved.
Licensed under the Glasgow Haskell Compiler License.
https://downloads.haskell.org/~ghc/9.14.1/docs/users_guide/exts/overloaded_lists.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API