Казалось бы, выражение Гамлета $case
должно быть чрезвычайно полезным, но я не могу понять, как оно будет сопоставляться с типом записи с несколькими конструкторами, за исключением сопоставления с образцом (с уникальным именем) для каждого из полей. Скажем, у меня есть тип данных,
data A = A1 { v1,v2,v3 :: Int }
| A2 { g :: Double}
В моем шаблоне я хотел бы отображать значения A1
иначе, чем значения A2
. Можно было бы подумать, что я мог бы просто сделать,
$case myA
$of a@(A1 {})
<p>This is an A1: #{show $ v1 a}
$of a@(A2 {})
<p>This is an A2: #{show $ g a}
К сожалению, этот фрагмент кода не скомпилируется из-за синтаксической ошибки, что говорит о том, что синтаксис @
не поддерживается. Если я уберу a@
, я получу еще одну синтаксическую ошибку, на этот раз предполагающую, что нотация скобок записи также не поддерживается.
Наконец, в отчаянии, раз можно попробовать,
$case myA
$of A1 _ _ _
...
Но, увы, даже это не компилируется (противоречащие определения _). Следовательно, кажется, что единственный вариант,
$case myA
$of A1 v1 v2 v3
...
Такое сопоставление шаблонов на основе порядка становится чрезвычайно утомительным для больших типов данных, особенно когда приходится давать имена каждому полю.
Итак, что мне здесь не хватает? Действительно ли анализ случаев в «Гамлете» так ограничен, как кажется? Каков рекомендуемый способ сопоставления с конструкторами АТД (и позже обращение к полям)? Является ли тот факт, что я даже хочу сделать такое сопоставление, признаком того, что я делаю это неправильно (ТМ)?