packages feed

comfort-array-0.5.2.1: src/Data/Array/Comfort/Shape/Tuple.hs

{-# LANGUAGE TypeFamilies #-}
module Data.Array.Comfort.Shape.Tuple where

import qualified Data.Array.Comfort.Shape as Shape
import Data.Complex (Complex((:+)))

import qualified Control.Monad.Trans.State as MS
import qualified Control.Applicative.HT as App
import Control.Applicative ((<$>))


get :: MS.State [a] a
get =
   MS.state $ \at ->
      case at of
         a:as -> (a,as)
         [] -> error "Shape.Tuple.get: no element left"

cons ::
   (Shape.ElementTuple shape) =>
   shape -> MS.State [a] (Shape.DataTuple shape a)
cons = Shape.indexTupleA (const get)


next :: MS.State Shape.Element Shape.Element
next = do
   ix <- MS.get
   MS.modify (\(Shape.Element k) -> Shape.Element (k+1))
   return ix


class (Shape.ElementTuple shape) => NestedTuple shape where
   decons :: Shape.DataTuple shape a -> MS.State Shape.Element (shape, [a])

instance NestedTuple () where
   decons () = return ((),[])

instance NestedTuple Shape.Element where
   decons a = flip (,) [a] <$> next

instance (NestedTuple a, NestedTuple b) => NestedTuple (a,b) where
   decons (a,b) =
      App.lift2 (\(ta,as) (tb,bs) -> ((ta,tb), as++bs)) (decons a) (decons b)

instance
   (NestedTuple a, NestedTuple b, NestedTuple c) =>
      NestedTuple (a,b,c) where
   decons (a,b,c) =
      App.lift3
         (\(ta,as) (tb,bs) (tc,cs) -> ((ta,tb,tc), as++bs++cs))
         (decons a) (decons b) (decons c)

instance
   (NestedTuple a, NestedTuple b, NestedTuple c, NestedTuple d) =>
      NestedTuple (a,b,c,d) where
   decons (a,b,c,d) =
      App.lift4
         (\(ta,as) (tb,bs) (tc,cs) (td,ds) -> ((ta,tb,tc,td), as++bs++cs++ds))
         (decons a) (decons b) (decons c) (decons d)

instance (NestedTuple a) => NestedTuple (Complex a) where
   decons (a:+b) =
      App.lift2 (\(ta,as) (tb,bs) -> ((ta:+tb), as++bs)) (decons a) (decons b)