Alex中的Haskell数据类型模式匹配

时间:2012-02-26 23:10:03

标签: haskell compiler-construction 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 个答案:

答案 0 :(得分:2)

每当你发现自己想要进行忽略这样的构造函数的模式匹配时,通常表示你想重构你的类型以获得一个新的枚举字段而不是旧的数据构造函数标签:

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

然后,您可以轻松地进行所需的模式匹配:

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

答案 1 :(得分:0)

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))

顺便说一下Alex(和Happy)并不是特别适合初学者。现在大多数人都使用Parsec / Attoparsec。使用Parsec,您可以在Haskell中编写解析代码,而不是使用预处理器。