根據你的後續問題,似乎泛型庫比Functor更適合你的情況。我建議只使用於SYB的wiki page給出的函數:
{-# 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
(更多細節有問題的極端情況維基)。 fmapData
的來電者不需要看到它。
該功能確實有比較真實的fmap
一些額外的要求:必須有Typeable
實例爲a
,並且Data
爲t a
。在你的情況下,t a
是Expr a
,這意味着你需要添加一個deriving Data
到Expr
的定義,以及Data
範圍內的任何a
你正在使用的範圍。
聽起來很像一個'Functor'。 'fmap'函數的類型爲'Functor f =>(a - > b) - >(f a - > f b)'。如果你說'Expr'是一個'Functor',那麼'fmap ::(a - > b) - >(Expr a - > Expr b)'。 – bheklilr
如果您想避免編寫'Functor'定義的樣板文件,您可以使用'DeriveFunctor'擴展名。 –
正是我在找的東西。把它寫成答案,我會接受它。謝謝! – jmite