yairchu
yairchu

Reputation: 24814

Define fmap in terms of the Data typeclass

Can one define fmap in terms of the Data typeclass from Data.Data?

It seems that using gfoldl one could not modify types.. Are there other combinators which can do this?

I'm guessing that it can't be done in the general case as one would have no way of only affecting the "Right" a's in an Either a a, but perhaps it could be done for some cases such as Maybe?

(I know that fmap is easily derivable but am still interested in whether this is achievable using Data)

Upvotes: 4

Views: 163

Answers (1)

jberryman
jberryman

Reputation: 16645

Here's on example using syb from here

{-# LANGUAGE DeriveDataTypeable, ScopedTypeVariables, FlexibleContexts #-}
import Data.Generics
import Unsafe.Coerce

{- | C tags the type that is actually parameterized, so to avoid touching the
Int when a ~ Int:

> data T a = T Int a

by changing the type (not representation) to:

> x :: T Int (C Int)
-}
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

Upvotes: 1

Related Questions