{-# LANGUAGE ScopedTypeVariables  #-}
{-# LANGUAGE FlexibleContexts     #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Data.Generics.Builders
-- Copyright   :  (c) 2008 Universiteit Utrecht
-- License     :  BSD-style
-- 
-- Maintainer  :  [email protected]
-- Stability   :  experimental
-- Portability :  non-portable
--
-- This module provides generic builder functions. These functions construct
-- values of a given type.
-----------------------------------------------------------------------------

module Data.Generics.Builders (empty, constrs) where

import Data.Data
import Data.Generics.Aliases (extB)

-- | Construct the empty value for a datatype. For algebraic datatypes, the
-- leftmost constructor is chosen.
empty :: forall a. Data a => a
empty = general 
      `extB` char 
      `extB` int
      `extB` integer
      `extB` float 
      `extB` double where
  -- Generic case
  general :: Data a => a
  general = fromConstrB empty (indexConstr (dataTypeOf general) 1)
  
  -- Base cases
  char    = '\NUL'
  int     = 0      :: Int
  integer = 0      :: Integer
  float   = 0.0    :: Float
  double  = 0.0    :: Double


-- | Return a list of values of a datatype. Each value is one of the possible
-- constructors of the datatype, populated with 'empty' values.
constrs :: forall a. Data a => [a]
constrs = general
      `extB` char
      `extB` int
      `extB` integer
      `extB` float
      `extB` double where
  -- Generic case
  general :: Data a => [a]
  general = map (fromConstrB empty)
              (dataTypeConstrs (dataTypeOf (unList general))) where
    unList :: Data a => [a] -> a
    unList = undefined

  -- Base cases
  char    = "\NUL"
  int     = [0   :: Int]
  integer = [0   :: Integer]
  float   = [0.0 :: Float]
  double  = [0.0 :: Double]