Spec-Zone.ru › Haskell 9

6.2.7. Обобщённые списковые включения (в стиле SQL)

TransformListComp
Начиная с:

6.10.1

Разрешает использовать синтаксис обобщённых списковых включений (в стиле SQL). Добавляет ключевые слова group, by и using.

Обобщённые списковые включения — это дальнейшее усовершенствование синтаксического сахара для списковых включений, позволяющее выполнять такие операции, как сортировка и группировка, знакомые по SQL. Они подробно описаны в статье Подробное рассмотрение списковых включений: включения с «order by» и «group by», за исключением того, что используемый нами синтаксис немного отличается от приведённого в статье.

Расширение включается с помощью расширения TransformListComp.

Пример:

employees = [ ("Simon", "MS", 80)
            , ("Erik", "MS", 100)
            , ("Phil", "Ed", 40)
            , ("Gordon", "Ed", 45)
            , ("Paul", "Yale", 60) ]

output = [ (the dept, sum salary)
         | (name, dept, salary) <- employees
         , then group by dept using groupWith
         , then sortWith by (sum salary)
         , then take 5 ]

В этом примере список output будет иметь значение:

[("Yale", 60), ("Ed", 85), ("MS", 180)]

Добавлены три ключевых слова: group, by и using. (Функции sortWith и groupWith не являются ключевыми словами; это обычные функции, экспортируемые модулем GHC.Exts.)

Добавлены пять новых форм квалификатора спискового включения, каждая из которых начинается с уже существующего ключевого слова then:

  • then f
    

    Эта конструкция требует, чтобы f имела тип forall a. [a] -> [a] . Пример её использования можно увидеть в мотивирующем примере: эта форма применяется для вызова take 5 .

  • then f by e
    

    Эта форма похожа на предыдущую, но позволяет создать функцию, которая будет передана f в качестве первого аргумента. Поэтому f должна иметь тип forall a. (a -> t) -> [a] -> [a]. Как видно из типа, эта функция позволяет f «извлекать» некоторую информацию из элементов преобразуемого списка.

    Пример показан в начале: sortWith передаётся функция, позволяющая ей определить sum salary для любого элемента преобразуемого спискового включения.

  • then group by e using f
    

    Это наиболее общая форма конструкций группировки. В этой форме f должна иметь тип forall a. (a -> t) -> [a] -> [[a]]. Как и в рассмотренном выше случае с then f by e, компилятор передаёт f первым аргументом функцию, позволяющую вычислять e для каждого элемента преобразуемого списка. Однако, в отличие от случая без группировки, f также разбивает список на несколько подсписков. Это означает, что после этой конструкции имена, объявленные в списковом включении до неё, ссылаются на списки возможных значений, а не на отдельные значения. Чтобы лучше это понять, рассмотрим пример:

    -- This works similarly to groupWith in GHC.Exts, but doesn't sort its input first
    groupRuns :: Eq b => (a -> b) -> [a] -> [[a]]
    groupRuns f = groupBy (\x y -> f x == f y)
    
    output = [ (the x, y)
    | x <- ([1..3] ++ [1..2])
    , y <- [4..6]
    , then group by x using groupRuns ]
    

    В результате переменная output примет значение:

    [(1, [4, 5, 6]), (2, [4, 5, 6]), (3, [4, 5, 6]), (1, [4, 5, 6]), (2, [4, 5, 6])]
    

    Обратите внимание, что мы использовали функцию the, чтобы преобразовать тип x из списка обратно в исходный числовой тип. Переменная y, напротив, остаётся списком, каким она стала после группировки.

  • then group using f
    

    В этой форме конструкции группировки f должна иметь тип forall a. [a] -> [[a]], который будет непосредственно использоваться для группировки уже построенного спискового включения. Пример этой формы:

    output = [ x
    | y <- [1..5]
    , x <- "hello"
    , then group using inits]
    

    В результате получится список, содержащий все префиксы слова «hello», записанного 5 раз:

    ["","h","he","hel","hell","hello","helloh","hellohe","hellohel","hellohell","hellohello","hellohelloh",...]
    

© 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/generalised_list_comprehensions.html

Spec-Zone.ru

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