私はGHC Genericsを学ぼうとしています。いくつかの例を見直した後、汎用のFunctor
インスタンスを作成しようとしました(GHCが自動的にそれらを引き出すことはできません)。しかし、ジェネリックスでパラメータ化されたデータ型をどのように扱うか分かりません。私が見た例はすべて*
です。これは可能ですか?はいの場合、どうですか? (私はSYBのような他の同様のフレームワークにも興味があります)GHC.Generics(または他の同様のフレームワーク)を使用して汎用Functorインスタンスを構築する方法は?
9
A
答えて
8
GHCジェネリックスを使用してたくさんのサンプル関数を探すには、generic-deriving
packageが最適です。そこにはFunctor
クラスの一般的な定義があります。 Generics.Deriving.Functor
からのコピー(少し簡略化):
class GFunctor' f where
gmap' :: (a -> b) -> f a -> f b
instance GFunctor' U1 where
gmap' _ U1 = U1
instance GFunctor' Par1 where
gmap' f (Par1 a) = Par1 (f a)
instance GFunctor' (K1 i c) where
gmap' _ (K1 a) = K1 a
instance (GFunctor f) => GFunctor' (Rec1 f) where
gmap' f (Rec1 a) = Rec1 (gmap f a)
instance (GFunctor' f) => GFunctor' (M1 i c f) where
gmap' f (M1 a) = M1 (gmap' f a)
instance (GFunctor' f, GFunctor' g) => GFunctor' (f :+: g) where
gmap' f (L1 a) = L1 (gmap' f a)
gmap' f (R1 a) = R1 (gmap' f a)
instance (GFunctor' f, GFunctor' g) => GFunctor' (f :*: g) where
gmap' f (a :*: b) = gmap' f a :*: gmap' f b
instance (GFunctor f, GFunctor' g) => GFunctor' (f :.: g) where
gmap' f (Comp1 x) = Comp1 (gmap (gmap' f) x)
class GFunctor f where
gmap :: (a -> b) -> f a -> f b
default gmap :: (Generic1 f, GFunctor' (Rep1 f))
=> (a -> b) -> f a -> f b
gmap = gmapdefault
gmapdefault :: (Generic1 f, GFunctor' (Rep1 f))
=> (a -> b) -> f a -> f b
gmapdefault f = to1 . gmap' f . from1
データ型でこれを使用するには、むしろGeneric
よりGeneric1
を導出する必要があります。 Generic1
表現の主な違いは、パラメータ位置をエンコードするPar1
データ型を使用することです。
3
データタイプが* -> *
の場合、Generic1
クラスがあります。これを使用した作業は、ほとんどの場合、種類が*
のデータ型と同じですが、パラメータにはPar1
があります。私は例えばunfoldable packageに使っています。
関連する問題
- 1. angular2を使用してハイブリッドアプリを構築するためのフレームワーク
- 2. RubyとActiveRecordを使用して排他INクエリを構築する方法は?
- 3. C++で同様のデータ構造をコピーするテンプレートベースの汎用的な方法はありますか?
- 4. angular2を使用してエキスパンドドロップダウンを構築する方法は?
- 5. マクロ内の型(ty)を使用してRustで構造体インスタンスを構築する方法は?
- 6. 外部フレームワークを使用するカスタムiOSフレームワークを構築する
- 7. ファクトリパターンを使用して、wcfクライアント用の汎用フレームワークを作成する方法については、
- 8. Functorを使用したコールバックパターン
- 9. このRコードをベクトル化する方法Plyr、Apply、または同様の方法を使用しますか?
- 10. xcassetsを使ってフレームワークを構築する方法
- 11. angularCLIを使用して別のフォルダに構築する方法
- 12. Javaマップ/リストを使用した同様の構造のグループ
- 13. インスタンス化の前に汎用クラスをパラメータ化する方法は?
- 14. 誰かがHudson(または他の同様のビルドシステム)をPerlで使用して成功しましたか?
- 15. SSISまたは同様の手法を使用して巨大な列をロード
- 16. エリクサーの場合と同様の構文 `receive 'を使用して
- 17. ANTを使用してDMGファイルを構築するクロスプラットフォームの方法は?
- 18. 他の証明書/店舗アカウント用のxcodeを使用してiosアプリケーションを構築する方法
- 19. VS2008はmsbuildを使用してASP.NET Webサイトを構築する方法は?
- 20. Appcelerator's Titaniumを使用して構築されたiOSネイティブアプリケーションで、janrainのウィジェットを使用する方法は?
- 21. 開発者のためのフレームワークを構築する方法
- 22. Sitecoreを使用してサイトマップを構築する方法
- 23. VSTSを使用してISPACを構築する方法
- 24. jQueryを使用してHTMLテーブルを構築する方法
- 25. Orientjsを使用してクエリを構築する方法
- 26. smackライブラリを使用してクライアントアプリケーションを構築する方法
- 27. Flex 3 Builderを使用してデスクトップアプリケーションを構築する方法
- 28. AssetManagerを使用してlibGDXでResourceManagerを構築する方法
- 29. HighChartsを使用してScadaアラートを構築する方法
- 30. JSONとjQueryを使用してツリーコントロールを構築する方法
GHCは自動的に 'Generic1'のインスタンスを派生しますか? –
@PetrPudlák完全には自動的にはありません。しかし、 'DeriveGeneric'言語拡張で' Generic1を導出する 'だけでなく、 'Deriving Generic'を使うこともできます(後者は、少なくとも1つのパラメータを持つデータ型に対してのみ機能し、最後のパラメータはkind *である)。 – kosmikus
@kosmikusありがとうございます。残念なことに私の目標ではもっと複雑な種類のものを使いたいので、Template Haskellを使わなければならないでしょう。 –