-
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)не будут объединены.