{-# LANGUAGE TypeFamilies, RankNTypes #-}

-- |Embedded array processing language: delayed arrays
--
--  Copyright (c) 2009 Manuel M T Chakravarty, Gabriele Keller, Sean Lee
--
--  License: BSD3
--
--- Description ---------------------------------------------------------------
--
--  Delayed arrays are represented by their representation function, which
--  enables the simple composition of many array operations.

module Data.Array.Accelerate.Array.Delayed (

  -- * Delayed array interface
  Delayable(delay, force), Delayed(..)

) where

-- friends
import Data.Array.Accelerate.Array.Sugar


-- Delayed arrays are characterised by the domain of an array and its functional
-- representation
-- 

class Delayable a where
  data Delayed a
  delay :: a -> Delayed a
  force :: Delayed a -> a
  
instance Delayable () where
  data Delayed () = DelayedUnit
  delay ()          = DelayedUnit
  force DelayedUnit = ()

instance Delayable (Array dim e) where
  data Delayed (Array dim e) 
    = (Ix dim, Elem e) => 
      DelayedArray { shapeDA :: ElemRepr dim
                   , repfDA  :: ElemRepr dim -> ElemRepr e
                   }
  delay arr@(Array sh _)    = DelayedArray sh (fromElem . (arr!) . toElem)
  force (DelayedArray sh f) = newArray (toElem sh) (toElem . f . fromElem)
  
instance (Delayable a1, Delayable a2) => Delayable (a1, a2) where
  data Delayed (a1, a2) = DelayedPair (Delayed a1) (Delayed a2)
  delay (a1, a2) = DelayedPair (delay a1) (delay a2)
  force (DelayedPair a1 a2) = (force a1, force a2)