Spec-Zone.ru › Haskell 9

6.7.2. Шаблоны представлений

ViewPatterns
Since:

6.10.1

Разрешить использование синтаксиса шаблонов представлений.

Шаблоны представлений включаются расширением языка ViewPatterns. Более подробную информацию и примеры шаблонов представлений можно найти на странице Wiki.

Шаблоны представлений чем-то похожи на охранные шаблоны, которые могут быть вложены внутри других шаблонов. Они являются удобным способом сопоставления с образцом значений абстрактных типов. Например, в реализации языка программирования мы можем представить синтаксис типов языка следующим образом:

type Typ

data TypView = Unit
             | Arrow Typ Typ

view :: Typ -> TypView

-- additional operations for constructing Typ's ...

Представление типа Typ является абстрактным, что позволяет реализациям использовать сложное представление (например, хеш-конструирование для управления совместным использованием). Без шаблонов представлений использование этой сигнатуры немного неудобно:

size :: Typ -> Integer
size t = case view t of
  Unit -> 1
  Arrow t1 t2 -> size t1 + size t2

Необходимо перебрать все случаи, а не использовать определение функции с помощью равенств. А ситуация еще хуже, когда сопоставление с t глубоко вложено внутри другого шаблона.

Шаблоны представлений позволяют вызывать функцию представления внутри шаблона и сопоставлять результат с образцом:

size (view -> Unit) = 1
size (view -> Arrow t1 t2) = size t1 + size t2

То есть, мы добавляем новый вид шаблона, записанный как ⟨выражение⟩ -> ⟨шаблон⟩, что означает «применить выражение к тому, с чем мы пытаемся сопоставить, а затем сопоставить результат этого применения с шаблоном». Выражение может быть любым выражением Haskell типа функции, и шаблоны представлений могут использоваться там, где используются шаблоны.

Семантика шаблона ( ⟨выражение⟩ -> ⟨шаблон⟩ ) следующая:

  • Область видимости: переменные, связанные шаблоном представления, — это переменные, связанные шаблоном ⟨шаблон⟩.

    Любые переменные в ⟨выражение⟩ — это связанные вхождения, но переменные, связанные «слева» в шаблоне, находятся в области видимости. Эта функция позволяет, например, использовать один аргумент функции в представлении другого аргумента. Например, функция clunky из Охранных шаблонов может быть записана с использованием шаблонов представлений следующим образом:

    clunky env (lookup env -> Just val1) (lookup env -> Just val2) = val1 + val2
    ...other equations for clunky...
    

    Более точно, правила области видимости следующие:

    • В одном шаблоне переменные, связанные шаблонами слева от выражения шаблона представления, находятся в области видимости. Например:

      example :: Maybe ((String -> Integer,Integer), String) -> Bool
      example (Just ((f,_), f -> 4)) = True
      

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

      example :: (String -> Integer) -> String -> Bool
      example f (f -> 4) = True
      

      То есть, область видимости такая же, как если бы аргументы с наложением были собраны в кортеж.

    • В взаимно рекурсивных связях, таких как let, where, или на верхнем уровне, шаблоны представлений в одном объявлении не могут ссылаться на переменные, связанные другими объявлениями. То есть каждое объявление должно быть самодостаточным. Например, следующая программа не допускается:

      let {(x -> y) = e1 ;
           (y -> x) = e2 } in x
      

    (Для некоторого расширения этой концепции проектирования см. #4061.

  • Типизация: Если ⟨выражение⟩ имеет тип ⟨T1⟩ -> ⟨T2⟩ и ⟨шаблон⟩ соответствует типу ⟨T2⟩, то весь шаблон представления соответствует типу ⟨T1⟩.
  • Сопоставление: К уравнениям в разделе 3.17.3 отчета Haskell 98 добавьте следующее:

    case v of { (e -> p) -> e1 ; _ -> e2 }
     =
    case (e v) of { p -> e1 ; _ -> e2 }
    

    То есть, чтобы сопоставить переменную ⟨v⟩ с шаблоном ( ⟨выражение⟩ -> ⟨шаблон⟩ ), вычислите ( ⟨выражение⟩ ⟨v⟩ ) и сопоставьте результат с шаблоном ⟨шаблон⟩.

  • Эффективность: Когда одна и та же функция представления применяется в нескольких ветвях определения функции или выражения case (например, в size выше), GHC пытается собрать эти применения в одно вложенное выражение case, так что функция представления применяется только один раз. Сопоставление шаблонов в GHC следует алгоритму матрицы, описанному в главе 4 The Implementation of Functional Programming Languages. Когда верхние строки первого столбца матрицы — это все шаблоны представлений с «тем же» выражением, эти шаблоны преобразуются в одно вложенное выражение case. Это включает, например, смежные шаблоны представлений, которые выстроены в кортеж, как в

    f ((view -> A, p1), p2) = e1
    f ((view -> B, p3), p4) = e2
    

    Текущее понятие того, когда два выражения шаблонов представлений являются «одинаковыми», очень ограничено: это не полное синтаксическое равенство. Однако оно включает переменные, литералы, применения и кортежи; например, два экземпляра view ("hi", "there") будут собраны. Однако текущая реализация не сравнивает до альфа-эквивалентности, поэтому два экземпляра (x, view x -> y) не будут объединены.

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

Spec-Zone.ru

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