Spec-Zone.ru › Haskell 9

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

TransformListComp
Since:

6.10.1

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

Обобщённые списочные включения представляют собой дальнейшее улучшение синтаксического сахара списочных включений, позволяющее выполнять такие операции, как сортировка и группировка, знакомые по SQL. Они подробно описаны в документе Comprehensive comprehensions: comprehensions with “order by” and “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 имело тип для всех 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.12.1/docs/users_guide/exts/generalised_list_comprehensions.html

Spec-Zone.ru

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