{-# LANGUAGE TypeOperators #-} {-# LANGUAGE FlexibleContexts #-} ----------------------------------------------------------------------------- -- | -- Module : Generics.EMGM.Functions.Map -- Copyright : (c) 2008 Universiteit Utrecht -- License : BSD3 -- -- Maintainer : generics@haskell.org -- Stability : experimental -- Portability : non-portable -- -- Summary: Generic function that applies a (non-generic) function to all -- elements contained in a polymorphic datatype. -- -- 'map' is a generic version of the @Prelude@ @map@ function. It works on all -- supported container datatypes of kind @* -> *@. The 'map' function is -- equivalent to 'fmap' after @deriving 'Functor'@ if that were possible. ----------------------------------------------------------------------------- module Generics.EMGM.Functions.Map ( Map(..), map, replace, bimap, ) where import Prelude hiding (map) import Generics.EMGM.Common ----------------------------------------------------------------------------- -- Types ----------------------------------------------------------------------------- -- | The type of a generic function that takes a value of one type and returns a -- value of a different type. newtype Map a b = Map { selMap :: a -> b } ----------------------------------------------------------------------------- -- Generic2 instance declaration ----------------------------------------------------------------------------- rconstantMap :: a -> a rconstantMap = id rsumMap :: Map a1 a2 -> Map b1 b2 -> a1 :+: b1 -> a2 :+: b2 rsumMap ra _ (L a) = L (selMap ra a) rsumMap _ rb (R b) = R (selMap rb b) rprodMap :: Map a1 a2 -> Map b1 b2 -> a1 :*: b1 -> a2 :*: b2 rprodMap ra rb (a :*: b) = selMap ra a :*: selMap rb b rtypeMap :: EP b r -> EP d a -> Map r a -> b -> d rtypeMap ep1 ep2 ra = to ep2 . selMap ra . from ep1 instance Generic2 Map where rconstant2 = Map rconstantMap rsum2 ra rb = Map (rsumMap ra rb) rprod2 ra rb = Map (rprodMap ra rb) rtype2 ep1 ep2 ra = Map (rtypeMap ep1 ep2 ra) ----------------------------------------------------------------------------- -- Exported functions ----------------------------------------------------------------------------- -- | Apply a function to all elements of a container datatype (kind @* -> *@). map :: (FRep2 Map f) => (a -> b) -> f a -> f b map = selMap . frep2 . Map -- | Replace all @a@-values in @as@ with @b@. replace :: (FRep2 Map f) => f a -> b -> f b replace as b = map (const b) as -- | Given a datatype @F a b@, @bimap f g@ applies the function @f :: a -> c@ to -- every @a@-element and the function @g :: b -> d@ to every @b@-element. The -- result is a value with transformed elements: @F c d@. bimap :: (BiFRep2 Map f) => (a -> c) -> (b -> d) -> f a b -> f c d bimap f g = selMap $ bifrep2 (Map f) (Map g)