emgm-0.4: src/Generics/EMGM/Functions/Meta.hs
--------------------------------------------------------------------------------
-- |
-- Module : Generics.EMGM.Functions.Meta
-- Copyright : (c) 2008 - 2010 Universiteit Utrecht
-- License : BSD3
--
-- Maintainer : generics@haskell.org
-- Stability : experimental
-- Portability : non-portable
--
-- Summary: Functions for extracting meta-information about the representation.
--------------------------------------------------------------------------------
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FunctionalDependencies #-}
module Generics.EMGM.Functions.Meta (
-- * Embedding-Projection Pair
HasEP(..),
-- * Constructor Description
Con(..),
conDescr,
-- * Label Descriptions
Lbls(..),
lblDescrs
) where
import Generics.EMGM.Base
--------------------------------------------------------------------------------
-- HasEP class
--------------------------------------------------------------------------------
-- | A class to reveal the embedding-projection pair for a given datatype and
-- its isomorphic representation type.
class HasEP a b | a -> b where
-- | The parameter is never evaluated, so @undefined@ is acceptable.
epOf :: a -> EP a b
--------------------------------------------------------------------------------
-- Type
--------------------------------------------------------------------------------
-- | The type of a generic function that takes one value and returns an optional
-- constructor description.
newtype Con a = Con { selConstructor :: a -> Maybe ConDescr }
--------------------------------------------------------------------------------
-- Generic instance declaration
--------------------------------------------------------------------------------
rsumConstructor :: Con a -> Con b -> a :+: b -> Maybe ConDescr
rsumConstructor ra _ (L a) = selConstructor ra a
rsumConstructor _ rb (R b) = selConstructor rb b
instance Generic Con where
rint = Con $ const Nothing
rinteger = Con $ const Nothing
rfloat = Con $ const Nothing
rdouble = Con $ const Nothing
rchar = Con $ const Nothing
runit = Con $ const Nothing
rsum ra rb = Con $ rsumConstructor ra rb
rprod _ _ = Con $ const Nothing
rcon cd _ = Con $ const $ Just cd
rlbl _ _ = Con $ const Nothing
rtype ep ra = Con $ selConstructor ra . from ep
--------------------------------------------------------------------------------
-- Exported function
--------------------------------------------------------------------------------
-- | Returns a constructor description if the value is not a primitive. The
-- argument is not evaluated and may be @undefined@.
conDescr :: (Rep Con a) => a -> Maybe ConDescr
conDescr = selConstructor rep
--------------------------------------------------------------------------------
-- Type
--------------------------------------------------------------------------------
-- | The type of a generic function that takes a boolean to limit recursion and
-- a value and returns a list of label descriptions for that constructor.
newtype Lbls a = Lbls { selLabels :: Bool -> a -> [LblDescr] }
--------------------------------------------------------------------------------
-- Generic instance declaration
--------------------------------------------------------------------------------
rsumLabels :: Lbls a -> Lbls b -> Bool -> a :+: b -> [LblDescr]
rsumLabels ra _ down (L a) = selLabels ra down a
rsumLabels _ rb down (R b) = selLabels rb down b
rprodLabels :: Lbls a -> Lbls b -> Bool -> a :*: b -> [LblDescr]
rprodLabels ra rb down (a :*: b) = selLabels ra down a ++ selLabels rb down b
check :: (a -> [b]) -> Bool -> a -> [b]
check act down val = if down then act val else []
rconLabels :: ConDescr -> Lbls a -> Bool -> a -> [LblDescr]
rconLabels _ ra = check $ selLabels ra False
rtypeLabels :: EP b a -> Lbls a -> Bool -> b -> [LblDescr]
rtypeLabels ep ra = check $ selLabels ra True . from ep
none :: a -> b -> [c]
none _ _ = []
one :: c -> a -> b -> [c]
one c _ _ = [c]
instance Generic Lbls where
rint = Lbls $ none
rinteger = Lbls $ none
rfloat = Lbls $ none
rdouble = Lbls $ none
rchar = Lbls $ none
runit = Lbls $ none
rsum ra rb = Lbls $ rsumLabels ra rb
rprod ra rb = Lbls $ rprodLabels ra rb
rcon cd ra = Lbls $ rconLabels cd ra
rlbl ld _ = Lbls $ one ld
rtype ep ra = Lbls $ rtypeLabels ep ra
--------------------------------------------------------------------------------
-- Exported function
--------------------------------------------------------------------------------
-- | Returns a list of descriptions for all labels in the head constructor. Does
-- not recurse into the children. The argument is not evaluated and may be
-- @undefined@.
lblDescrs :: (Rep Lbls a) => a -> [LblDescr]
lblDescrs = selLabels rep True