{-# LANGUAGE OverlappingInstances, UndecidableInstances, FlexibleContexts, FlexibleInstances #-} ----------------------------------------------------------------------------- -- | -- Module : HAppS.Data.Normalize -- Copyright : (c) 2007 HAppS LLC -- License : BSD3 -- -- Maintainer : AlexJacobson@HAppS.org -- Stability : experimental -- Portability : Not portable -- -- Normalizing Haskell values. -- ----------------------------------------------------------------------------- module HAppS.Data.Normalize ( -- * The interface Normalize(normalize, normalizeRecursively), -- * Writing your own instances defaultNormalize, defaultNormalizeRecursively, -- * Advanced usage NormalizeD(..), normalizeProxy, ) where import Data.Generics.SYB.WithClass.Basics -- | The 'Normalize' class provides a 'normalize' function, which -- is intended to normalize values only at the top-level constructor, -- and a 'normalizeRecursively' function, which is intended to -- normalize all the subvalues and then normalize the top-level -- constructor. -- -- There is a default instance that matches all types, where 'normalize' -- is 'id' and 'normalizeRecursively' applies 'normalizeRecursively' to -- all of its children and then 'normalize' to the result. -- -- If you want to actually do some normalization for a certain type, -- then just define an instance for that type; this will take precedence -- over the default instance. class Data NormalizeD a => Normalize a where normalize :: a -> a normalize = defaultNormalize normalizeRecursively :: a -> a normalizeRecursively = defaultNormalizeRecursively -- | This is the 'normalize' function in the default 'Normalize' -- instance. It may be a useful building block when writing your own -- instances. defaultNormalize :: Normalize a => a -> a defaultNormalize x = x -- | This is the 'normalizeRecursively' function in the default -- 'Normalize' instance. It may be a useful building block when writing -- your own instances. defaultNormalizeRecursively :: Normalize a => a -> a defaultNormalizeRecursively x = normalize $ gmapT normalizeProxy (normalizeRecursivelyD dict) x -- | When writing your own generic functions for 'Normalize' you may -- need to access the class methods through this datatype rather than -- directly. data NormalizeD a = NormalizeD { normalizeD :: a -> a, normalizeRecursivelyD :: a -> a } -- | When writing your own generic functions for 'Normalize' you may -- need this, the proxy value. normalizeProxy :: Proxy NormalizeD normalizeProxy = error "normalizeProxy" instance Normalize t => Sat (NormalizeD t) where dict = NormalizeD { normalizeD = normalize, normalizeRecursivelyD = normalizeRecursively } instance Data NormalizeD a => Normalize a