私はのいずれかのの再帰的文法データ型とそのデータ型の表現をとることができ、同じ種類のすべての部分式のリストを生成するようなコードを作成しようとしていますその型の再帰でscan
のようにします。再帰型レンダリング
付属の玩具電卓の文法タイプEExp
については、以下の2つの手動の例を書いています。最初の例では、Lensライブラリのプリズムとレンズを使用していますが、eg1
の式の1つでは動作しますが、2番目の関数はハンドリングされたコードを使用しますが、EExp
の式では動作します。
理想的には、テンプレートのhaskellなどを使用して、そのタイプ(プリズム/レンズのような)の式の各サブ式に焦点を当てる再帰関数を自動的に構築することができます。それに与えられたあらゆる表現のすべての部分のリストを出してください。
私はちょっと試してみてください。どんな助けも本当にありがとう!
import qualified Control.Lens as Lens
import qualified Control.Lens.TH as LTH
-- Syntax for toy language
data EExp a
= ELit a
| EAdd (EExp a) (EExp a)
| EMul (EExp a) (EExp a)
| ESub (EExp a) (EExp a)
deriving Show
-- build out a set of focus functions using lens/TH
LTH.makePrisms ''EExp
-- An example "text" in the Syntax
eg1 :: EExp Int
eg1 = EAdd
(ELit 1)
(EAdd (ELit 2) (ELit 0))
-- using lenses, we build out all the
-- EExp possibilities from the example "text":
lensedOptions :: Show a => EExp a -> [EExp a]
lensedOptions exp =
let
maybeGet l = Lens.preview l exp
listMaybes =
[ Just exp
, maybeGet (_EAdd.(Lens._1))
, maybeGet (_EAdd.(Lens._2))
, maybeGet (_EAdd.(Lens._2)._EAdd.(Lens._1))
, maybeGet (_EAdd.(Lens._2)._EAdd.(Lens._2))
]
in
maybe [] id $ sequenceA listMaybes
printEm :: IO()
printEm = sequence_ $ map print $ lensedOptions eg1
-- using handwritten code, we build out all the
-- EExp possibilities from the example "text":
buildOptions :: Show a => EExp a -> [EExp a]
buildOptions exp =
let
buildBinOpts e1 e2 = [exp] ++ buildOptions e1 ++ buildOptions e2
in
case exp of
ELit i -> [exp]
EAdd e1 e2 ->
buildBinOpts e1 e2
EMul e1 e2 ->
buildBinOpts e1 e2
ESub e1 e2 ->
buildBinOpts e1 e2
printEm2 :: IO()
printEm2 = sequence_ $ map print $ buildOptions eg1
恐ろしい! <3とてもありがとう@haoformayor。私は間もなくその論文をすぐに読んでいくつもりです(私は、元々は興味のあることからハズレでジェネリックプログラミングを検討していましたが、何よりも面白い興味をそそられていました)。 –
私のGHCによれば、この拡張は実際には 'DeriveDataTypeable'と呼ばれています。あなたが書いたものを訂正します。 –
また、あなたが書いたコードを動作させることができません。あなたは答えを出す前にそれをコンパイルしようとしましたか?私は最初に自分で試してみるべきだったので、少し早めにあなたの答えを受け入れたと思います。ただ今になって。あなたが多分 'universeOf'を意味するのだろうか?私はこれ以上のことを学ぶ必要があります。 –