2012-02-26 40 views
0

假設我有一個數據類型在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. 

有什麼建議?

+0

編寫從不同的令牌中提取AlexPosn領域的功能。 – Ingo 2012-02-27 01:03:36

回答

2

當你發現自己想要做的模式匹配忽略這樣的構造,它通常是要重構你的類型有一個新的枚舉領域,而不是舊的數據構造的標籤標誌:

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

然後,你可以很容易做到你想要的模式匹配:

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

這是「每個人」使用的成語,但通常使用不同的命名方案(人們必須使用相同的原始示例)。枚舉一個數據類型中的所有標記,然後將枚舉包含在另一個數據類型及其源位置中。人們調用包裝的標記類型和源位置「Lexeme」。 – 2012-02-27 13:45:07

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

通過亞歷克斯(和快樂)的方式並不特別適合初學者。現在大多數人使用Parsec/Attoparsec。使用Parsec,您可以在Haskell中編寫解析代碼,而不是使用預處理器。