Использование гамлетовского случая $case с записями и АТД

Казалось бы, выражение Гамлета $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
      ...

Такое сопоставление шаблонов на основе порядка становится чрезвычайно утомительным для больших типов данных, особенно когда приходится давать имена каждому полю.

Итак, что мне здесь не хватает? Действительно ли анализ случаев в «Гамлете» так ограничен, как кажется? Каков рекомендуемый способ сопоставления с конструкторами АТД (и позже обращение к полям)? Является ли тот факт, что я даже хочу сделать такое сопоставление, признаком того, что я делаю это неправильно (ТМ)?


person bgamari    schedule 06.11.2012    source источник
comment
Сопоставление регистров почти всегда является лучшим подходом, так что вы не ошибетесь. Это опасность работы в DSL, и именно поэтому многие выступают за то, чтобы сам Haskell всегда был вашим DSL.   -  person Gabriel Gonzalez    schedule 06.11.2012
comment
Я не очень ясно выразился по этому поводу, но я имел в виду, что, возможно, мне не следует проводить анализ случаев в шаблоне. Я подумал, что отсутствие в «Гамлете» богатого примитива анализа случаев было признаком того, что мне не следует помещать в шаблон слишком много логики.   -  person bgamari    schedule 06.11.2012


Ответы (1)


Вы можете отслеживать обработку гамлета.

Ответ находится в скрытом модуле Text.Hamlet.Parse, где

controlOf = do
    _   <- try $ string "$of"
    pat <- many1 $ try $ spaces >> ident
    _   <- spaceTabs
    eol
    return $ LineOf pat

where
  ident = Ident <$> many1 (alphaNum <|> char '_' <|> char '\'')

поэтому принимается только последовательность из одного или нескольких (пробелов, за которыми следует (идентификатор или подстановочный знак)).

Вы можете расширить его отсюда.

Ваше здоровье!

person Gabriel Riba    schedule 06.11.2012
comment
Я так понимаю, это просто недостаток текущей реализации $case? Я мог бы попробовать добавить поддержку синтаксиса @, хотя боюсь, что полный синтаксис записи немного больше, чем хотелось бы. - person bgamari; 06.11.2012