Соответствие шаблону типа данных на Haskell в Alex

Предположим, у меня есть тип данных в Haskell, например:

data Token = THEN AlexPosn
            | ELSE AlexPosn

от Алекса я получаю это:

data AlexPosn = AlexPn !Int !Int !Int
    deriving (Eq,Show)

Я могу сделать сопоставление с образцом, как это:

eat_token :: Token -> [Token] -> [Token]
eat_token  (THEN p1)((THEN p2):rest) = rest
eat_token  (ELSE p1)((ELSE p2):rest) = rest

Но то, что я действительно хочу достичь здесь, это:

eat_token  (_ p) tk2 = error "Syntax Error at:"++(show p)

Тем не менее, я получаю:

Parse error in pattern.

Какие-либо предложения?

2 ответа

Решение

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

data Token = Token TokenType AlexPosn
data TokenType = THEN | ELSE

Затем вы можете легко выполнить поиск по шаблону:

eat_token (Token _ p) tk2 = error $ "Syntax Error at: " ++ show p
eat_token  (_ p) tk2 = error "Syntax Error at:"++(show p)

Haskell не поддерживает анонимные конструкторы (т. Е. Использование подчеркивания для сопоставления с образцом любого конструктора), даже если все конструкторы типа данных имеют одинаковые элементы.

Вы можете использовать поля записи в вашем типе данных, это автоматически создаст функцию доступа:

data Token = THEN { src_pos :: AlexPosn }
           | ELSE { src_pos :: AlexPosn }

Это создает функцию src_pos которую вы можете использовать как любую другую функцию:

eat_token tok ts2 = error "Syntax Error at: " ++ (show (src_pos tok))

Кстати, Алекс (и Хэппи) не особенно дружелюбны для начинающих. В настоящее время большинство людей используют Parsec / Attoparsec. С Parsec вы пишете код синтаксического анализа на Хаскеле, а не с препроцессором.

Другие вопросы по тегам