我目前正在實施Lexer/Parser。還有一兩件事,我的錯誤是,目前在我Parser.hs一半的我的代碼將被專用於僅僅讓單個標記:如何避免過多的樣板匹配構造函數
對於小數據類型是這樣的:
data Tok
= IdLower String
| IdUpper String
| IdSymbol String
| IdColon String
| Equals
| Newline
我似乎需要這樣的事:
idLower :: Parser String
idLower = get >>= \s -> if
| (_, IdLower n) :- xs <- s -> put xs *> pure n
| (l, t) :- _ <- s -> throwError [(l, "Unexpected " <> description t)]
| Nil l <- s -> throwError [(l, "Unexpected end of input")]
idUpper :: Parser String
idUpper = get >>= \s -> if
| (_, IdUpper n) :- xs <- s -> put xs *> pure n
| (l, t) :- _ <- s -> throwError [(l, "Unexpected " <> description t)]
| Nil l <- s -> throwError [(l, "Unexpected end of input")]
idSymbol :: Parser String
idSymbol = get >>= \s -> if
| (_, IdSymbol n) :- xs <- s -> put xs *> pure n
| (l, t) :- _ <- s -> throwError [(l, "Unexpected " <> description t)]
| Nil l <- s -> throwError [(l, "Unexpected end of input")]
idColon :: Parser String
idColon = get >>= \s -> if
| (_, IdColon n) :- xs <- s -> put xs *> pure n
| (l, t) :- _ <- s -> throwError [(l, "Unexpected " <> description t)]
| Nil l <- s -> throwError [(l, "Unexpected end of input")]
equals :: Parser()
equals = get >>= \s -> if
| (_, Equals) :- xs <- s -> put xs
| (l, t) :- _ <- s -> throwError [(l, "Unexpected " <> description t)]
| Nil l <- s -> throwError [(l, "Unexpected end of input")]
newline :: Parser()
newline = get >>= \s -> if
| (_, Newline) :- xs <- s -> put xs
| (l, t) :- _ <- s -> throwError [(l, "Unexpected " <> description t)]
| Nil l <- s -> throwError [(l, "Unexpected end of input")]
這就好比是99%重複的代碼,它們之間唯一的區別是使用的構造,以及我是否有類似pure n
對於有內容的人。
我嘗試過重構一下,以便每個符號只有一個Tok -> Maybe()
或Tok -> Maybe String
函數,然後創建一個高階函數,將這些函數作爲參數。但是每個Tok -> Maybe a
函數需要3行加上1行的間隔符,現在我需要另一個更高階的函數來支持它,如果我想要shorthands,所以我可以使用idLower
而不是getToken idLower
,那麼我最終的代碼總數,如果不是更多!
我只是真的希望有一個替代上述。現在我知道我可以通過創建一個自動失敗的函數來減少一些重複,這個函數總是會調用相關的throwError
,如果第一個守衛沒有命中,我可以推遲這個函數,但即使如此,這仍然相當嚴重。
我想避免模板哈斯克爾,所以我仍然希望有一個無TH的解決方案。但有了這個說法,這仍然看起來像是一個非常有效的解決方案,而且我有一種感覺,如果沒有TH,很難做到這一點,所以謝謝! – semicolon
@semicolon原則上,您也可以使用泛型編程來派生棱鏡。這會比使用TH更容易接受嗎? – kosmikus
這就是你在其他答案中所做的事情嗎? – semicolon