content: -- ------------------------------------------------------------
  
  {- |
     Module     : Control.FlatSeq
     Copyright  : Copyright (C) 2011 Uwe Schmidt
     License    : MIT
  
     Maintainer : Uwe Schmidt (uwe\@fh-wedel.de)
     Stability  : experimental
     Portability: portable
  
     Force evaluation like deepseq in Control.DeepSeq,
     but control the depth of evaluation.
     flatseq may evaluate more than seq but less than deepseq
  
  -}
  
  -- ------------------------------------------------------------
  
  module Control.FlatSeq
  where
  
  import Data.Word
  
  -- ------------------------------------------------------------
  
  infixr 0 $!!
  
  ($!!)                           :: WNFData a => (a -> b) -> a -> b
  f $!! x                         = rwnf x `seq` f x
  {-# INLINE ($!!) #-}
  
  flatseq                         :: WNFData a => a -> b -> b
  flatseq a b                     = rwnf a `seq` b
  {-# INLINE flatseq #-}
  
  rlnf                            :: (a -> ()) -> [a] -> ()
  rlnf _ []                       = ()
  rlnf r (x:xs)                   = r x `seq` rlnf r xs
  {-# INLINE rlnf #-}
  
  -- | A class of types that can be partially evaluated, but evaluation can be propagated deeper than WHNF
  
  class WNFData a where
      -- | Default for rwnf is reduction to WHNF
      rwnf                        :: a -> ()
      rwnf a                      = a `seq` ()
      {-# INLINE rwnf #-}
  
      -- | Default for rwnf2 is rwnf
      rwnf2                       :: a -> ()
      rwnf2                       = rwnf
      {-# INLINE rwnf2 #-}
  
  instance WNFData Int 
  instance WNFData Integer
  instance WNFData Float
  instance WNFData Double
  
  instance WNFData Char
  instance WNFData Bool
  instance WNFData ()
  
  instance WNFData Word
  instance WNFData Word8
  instance WNFData Word16
  instance WNFData Word32
  instance WNFData Word64
  
  instance WNFData a => WNFData [a] where
      rwnf []                     = ()
      rwnf (x:xs)                 = x `seq` rwnf xs
      {-# INLINE rwnf #-}
  
  instance (WNFData a, WNFData b) => WNFData (a,b) where
      rwnf (x,y)                  = rwnf x `seq` rwnf y
      {-# INLINE rwnf #-}
  
  instance (WNFData a, WNFData b, WNFData c) => WNFData (a,b,c) where
      rwnf (x,y,z)                = rwnf x `seq` rwnf y `seq` rwnf z 
      {-# INLINE rwnf #-}
  
  instance (WNFData a, WNFData b, WNFData c, WNFData d) => WNFData (a,b,c,d) where
      rwnf (x1,x2,x3,x4)          = rwnf x1 `seq` 
                                    rwnf x2 `seq` 
                                    rwnf x3 `seq` 
                                    rwnf x4 
      {-# INLINE rwnf #-}
  
  -- ------------------------------------------------------------
  