私は(GADT形式で、以下に示す)のデータ型があります:私は何をしたいかADTのコンストラクタの引数をマップする方法は?
data Test a where
C1 :: Int -> a -> Test a
C2 :: Test a -> Test a -> a -> Test a
C3 :: Test a -> a -> Test a
...
は、その後、コンストラクタでTest a
の任意のインスタンスに一般的にいくつかの機能Monoid m => Test a -> m
を適用することができることですmappend
それをすべて。
したがって、たとえば、F与えられた:私はしたくないことを除いて
g :: Monoid m => (Test a -> m) -> Test a -> m
g f [email protected](C1 Int _) = f v
g f (C2 x y _) = f x `mappend` f y
g f (C3 x _) = f x
...
:
f :: Test a -> [Int]
f (C1 n _) = [n]
f _ = []
私はそうのような各コンストラクタの引数の上にこれをマッピングすることができ、いくつかの関数gを希望g
を書くには、サポートされているデータ型に対してこれを行うことができるg
のジェネリック版を書いてみたい(GHC.Genericsはこれに適していると思っているが、タイプを正しく取得できなかった)。すなわち 私は面白いビットから自分のデータ構造(mappend
ベース倍とf
の繰り返しアプリケーション)を横断する実際の仕組み(上記g
でC1
の端子ケース)
任意のアイデアを分離したいのですが?
'C1'コンストラクタで作られた値だけに' f'を適用することになっていますか?なぜ、「C2」または「C3」コンストラクタではありませんか?それは再帰的引数を持たないコンストラクタのためだけですか? 'C4 Int(Test a)'コンストラクタまたは 'C5 Int'コンストラクタがあった場合、どうなりますか? –
いいえ、 'f'は' Test a'パーツを選ぶことができるので、 'f'の定義が与えられているので、' g'は 'C4 ir'と' ] ''(またはmempty)を返します。あなたのコメントは、 'f'が' f'を 'f'を呼び出すよりも簡単に関数を呼び出す方が簡単かもしれないことを実際に気付かせました。 – Chetan
GHC.Genericsは良い賭けです。これまで使ったことがない人は、使いにくいかもしれません。 [the the paper](https://www.microsoft.com/en-us/research/wp-content/uploads/2003/01/hmap.pdf)を読んだことがありますか? - 私が紙を読んだとき、それは暗い呪文ではなくなり、有用な道具になり始めました、それを想像してください! – luqui