Соответствие шаблону типа данных на 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 вы пишете код синтаксического анализа на Хаскеле, а не с препроцессором.