简体   繁体   中英

Haskell data type pattern matching in Alex

Suppose I have a data type in Haskell like this:

data Token = THEN AlexPosn
            | ELSE AlexPosn

from Alex, I get that:

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

I am able to do pattern matching like this:

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

But what I really want to accomplish here is this:

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

However, I get:

Parse error in pattern.

Any suggestions?

Whenever you find yourself wanting to do pattern matching that ignores the constructor like that, it's usually a sign that you want to refactor your type to have a new enumeration field instead of the old data constructor labels:

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

Then, you can easily do the pattern match you wanted:

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

Haskell does not support anonymous constructors (ie using underscores to pattern match any constructor) even if all the constructors of a data type have the same elements.

You can use record fields in your datatype, this will automatically create an accessor function:

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

This creates a function src_pos which you can use like any other function:

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

By the way Alex (and Happy) aren't particularly beginner friendly. Most people use Parsec / Attoparsec nowadays. With Parsec you write the parsing code in Haskell rather than with a preprocessor.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM