現在、私はLexer/Parserを実装中です。そして、私は私のParser.hsでの私のコードの現在の半分は、単に単一のトークン取得するために専用されようとしているということですバグ一つのこと:一致するコンストラクタの過度の定型文を避ける方法
data Tok
= IdLower String
| IdUpper String
| IdSymbol String
| IdColon String
| Equals
| Newline
I:このような小さなデータタイプについて
をこのような何か必要があるように見える:
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
という関数を1つだけ持つようにリファクタリングしてから、これらの関数をパラメータとして使用する高次関数を作成しました。しかし、それぞれのTok -> Maybe a
関数は、3行と1行のスペーサーを取ります。そして今、私はそれをサポートするために別の高次関数が必要です。もし簡略化したいのであれば、getToken idLower
の代わりにidLower
を使うことができます。 、それ以上ではない!
私はちょうど上記に代わるものがあることを本当に望んでいます。今私はおそらく最初のガードがヒットしない場合に延期することができる関連するthrowError
を常に呼び出す自動的に機能しない関数を作成することによって、少し重複を減らすことができることを知っています。
次のようになります。これは
Data.Type.Equality
からtestEquality
は(残念ながら現在は再びTHを使用する場合を除き、任意の簡単な方法で導き出すことができない)何をするかですハスケルので、私はまだTHフリーのソリューションがあることを願っています。しかし、それはまだこれが信じられないほど効果的な解決策のように見え、THなしでこれを行うのは難しいかもしれないという気持ちがあるので、ありがとう! – semicolon@semicolon原理的には、汎用プログラミングを使用してプリズムを導出することもできます。それはTHを使うよりも容認できるでしょうか? – kosmikus
それはあなたの他の答えでやっていることですか? – semicolon