あなたのフォローアップの質問に基づいて、ジェネリック ライブラリは Functor よりもあなたの状況に適しているようです。SYB のwiki ページにある関数を使用することをお勧めします。
{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables, FlexibleContexts #-}
import Data.Generics
import Unsafe.Coerce
newtype C a = C a deriving (Data,Typeable)
fmapData :: forall t a b. (Typeable a, Data (t (C a)), Data (t a)) =>
(a -> b) -> t a -> t b
fmapData f input = uc . everywhere (mkT $ \(x::C a) -> uc (f (uc x)))
$ (uc input :: t (C a))
where uc = unsafeCoerce
余分なタイプの理由はC
、同じタイプのフィールドが発生するという問題のあるコーナー ケースを回避するためですa
(詳細は wiki を参照)。の呼び出し元はfmapData
それを見る必要はありません。
この関数には、実際の と比較していくつかの追加要件があります。 forおよびforfmap
のインスタンスが必要です。あなたの場合はです。つまり、 の定義にa を追加するだけでなく、使用しているもののスコープ内にインスタンスを含める必要があります。Typeable
a
Data
t a
t a
Expr a
deriving Data
Expr
Data
a