Spec-Zone.ru › Haskell 9

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

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

© 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.12.1/docs/users_guide/exts/overloaded_lists.html

Spec-Zone.ru

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