happstack-data-0.2.1: src/Happstack/Data/Normalize.hs
{-# LANGUAGE OverlappingInstances, UndecidableInstances,
FlexibleContexts, FlexibleInstances #-}
-----------------------------------------------------------------------------
-- |
-- Module : Happstack.Data.Normalize
-- Copyright : (c) Happstack.com 2009; (c) HAppS LLC 2007
-- License : BSD3
--
-- Maintainer : happs@googlegroups.com
-- Stability : experimental
-- Portability : Not portable
--
-- Normalizing Haskell values.
--
-----------------------------------------------------------------------------
module Happstack.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 = normalize . gmapT normalizeProxy (normalizeRecursivelyD dict)
-- | 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