packages feed

tup-functor (empty) → 0.1

raw patch · 9 files changed

+560/−0 lines, 9 filesdep +basedep +haskell-src-extsdep +parsec2setup-changed

Dependencies added: base, haskell-src-exts, parsec2

Files

+ Data/Tup.hs view
@@ -0,0 +1,23 @@+
+-- | This small library defines data types 'Tup1', 'Tup2' ... 'Tup9' for homogeneous tuples of small size (both strict and lazy), 
+-- and various instances for them, most notably 'Functor' and 'Applicative'. We also have a 'Tup' type class:
+-- 
+-- > class Tup f where
+-- >   tupSize     :: f a -> Int
+-- >   tupToList   :: f a -> [a]
+-- >   tupFromList :: [a] -> f a 
+-- >   tupUndef    :: f a -> a
+--
+-- Also included is a very simple preprocesszor @tpp@ which translates
+-- the syntax @\{\{a,b,c\}\}@ into @(Tup3 a b c)@.
+
+module Data.Tup 
+  ( module Data.Tup.Class
+  , module Data.Tup.Lazy 
+  ) 
+  where
+
+import Control.Applicative ( Applicative )     -- only for Haddock
+
+import Data.Tup.Class
+import Data.Tup.Lazy
+ Data/Tup/Class.hs view
@@ -0,0 +1,58 @@+
+module Data.Tup.Class where
+
+--------------------------------------------------------------------------------
+
+import Control.Applicative
+import Data.List
+
+--------------------------------------------------------------------------------
+-- * the Tup class
+
+class (Functor f, Applicative f) => Tup f where
+  tupSize     :: f a -> Int
+  tupToList   :: f a -> [a]
+  tupFromList :: [a] -> f a
+
+  tupUndef    :: f a -> a
+  tupUndef     = undefined
+
+--------------------------------------------------------------------------------
+-- * misc 
+
+-- | Safe version of 'tupFromList'.
+maybeTupFromList :: Tup f => [a] -> Maybe (f a)
+maybeTupFromList xs = result where
+  result = if length xs == tupSize (undef result) 
+    then Just (tupFromList xs)
+    else Nothing    
+  undef :: Maybe a -> a
+  undef _ = undefined
+
+-- | Transpose a Tup of Tups.
+transposeTup :: (Tup f, Tup g) => f (g a) -> g (f a)
+transposeTup = tupFromList . (map tupFromList) . transpose . (map tupToList) . tupToList
+
+--------------------------------------------------------------------------------
+-- * zipping 
+
+zipTupWith :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
+zipTupWith f t1 t2 = f <$> t1 <*> t2
+
+zipTupWith3 :: Applicative f => (a -> b -> c -> d) -> f a -> f b -> f c -> f d
+zipTupWith3 f t1 t2 t3 = f <$> t1 <*> t2 <*> t3
+
+zipTupWith4 :: Applicative f => (a -> b -> c -> d -> e) -> f a -> f b -> f c -> f d -> f e
+zipTupWith4 f t1 t2 t3 t4 = f <$> t1 <*> t2 <*> t3 <*> t4
+
+zipTup :: Applicative f => f a -> f b -> f (a,b)
+zipTup t1 t2 = (,) <$> t1 <*> t2
+
+zipTup3 :: Applicative f => f a -> f b -> f c -> f (a,b,c)
+zipTup3 t1 t2 t3 = (,,) <$> t1 <*> t2 <*> t3
+
+zipTup4 :: Applicative f => f a -> f b -> f c -> f d -> f (a,b,c,d)
+zipTup4 t1 t2 t3 t4 = (,,,) <$> t1 <*> t2 <*> t3 <*> t4
+
+--------------------------------------------------------------------------------
+
+ Data/Tup/Lazy.hs view
@@ -0,0 +1,9 @@+
+{-# LANGUAGE CPP, DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
+
+module Data.Tup.Lazy where
+
+#define A a
+
+#include "Tup.inc"
+
+ Data/Tup/Strict.hs view
@@ -0,0 +1,9 @@+
+{-# LANGUAGE CPP, DeriveFunctor, DeriveFoldable, DeriveTraversable #-}
+
+module Data.Tup.Strict where
+
+#define A !a
+
+#include "Tup.inc"
+
+ Data/Tup/Tup.inc view
@@ -0,0 +1,233 @@+
+--------------------------------------------------------------------------------
+
+import Control.Applicative
+
+import Data.List
+import Data.Foldable
+import Data.Traversable
+import Data.Monoid
+
+import Foreign.Ptr
+import Foreign.Storable
+import Foreign.Marshal
+
+import Data.Tup.Class
+
+--------------------------------------------------------------------------------
+-- * data type declarations
+
+data Tup1 a = Tup1 A                  deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+data Tup2 a = Tup2 A A                deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+data Tup3 a = Tup3 A A A              deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+data Tup4 a = Tup4 A A A A            deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+data Tup5 a = Tup5 A A A A A          deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+data Tup6 a = Tup6 A A A A A A        deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+data Tup7 a = Tup7 A A A A A A A      deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+data Tup8 a = Tup8 A A A A A A A A    deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+data Tup9 a = Tup9 A A A A A A A A A  deriving (Eq,Ord,Show,Read,Functor,Foldable,Traversable)
+
+--------------------------------------------------------------------------------
+-- * \"tupping\"
+
+tupTup :: Applicative f => f a -> f a -> f (Tup2 a)
+tupTup t1 t2 = Tup2 <$> t1 <*> t2
+
+tupTup3 :: Applicative f => f a -> f a -> f a -> f (Tup3 a)
+tupTup3 t1 t2 t3 = Tup3 <$> t1 <*> t2 <*> t3
+
+tupTup4 :: Applicative f => f a -> f a -> f a -> f a -> f (Tup4 a)
+tupTup4 t1 t2 t3 t4 = Tup4 <$> t1 <*> t2 <*> t3 <*> t4
+
+tupTup5 :: Applicative f => f a -> f a -> f a -> f a -> f a -> f (Tup5 a)
+tupTup5 t1 t2 t3 t4 t5 = Tup5 <$> t1 <*> t2 <*> t3 <*> t4 <*> t5
+
+--------------------------------------------------------------------------------
+-- * instances
+
+instance Tup Tup1 where
+  tupSize _ = 1
+  tupToList (Tup1 x1) = [x1]
+  tupFromList [x1] = Tup1 x1
+  tupFromList _ = error "tupFromList: list should have length 1"
+
+instance Tup Tup2 where
+  tupSize _ = 2
+  tupToList (Tup2 x1 x2) = [x1,x2]
+  tupFromList [x1,x2] = Tup2 x1 x2
+  tupFromList _ = error "tupFromList: list should have length 2"
+
+instance Tup Tup3 where
+  tupSize _ = 3
+  tupToList (Tup3 x1 x2 x3) = [x1,x2,x3]
+  tupFromList [x1,x2,x3] = Tup3 x1 x2 x3
+  tupFromList _ = error "tupFromList: list should have length 3"
+
+instance Tup Tup4 where
+  tupSize _ = 4
+  tupToList (Tup4 x1 x2 x3 x4) = [x1,x2,x3,x4]
+  tupFromList [x1,x2,x3,x4] = Tup4 x1 x2 x3 x4
+  tupFromList _ = error "tupFromList: list should have length 4"
+
+instance Tup Tup5 where
+  tupSize _ = 5
+  tupToList (Tup5 x1 x2 x3 x4 x5) = [x1,x2,x3,x4,x5]
+  tupFromList [x1,x2,x3,x4,x5] = Tup5 x1 x2 x3 x4 x5
+  tupFromList _ = error "tupFromList: list should have length 5"
+
+instance Tup Tup6 where
+  tupSize _ = 6
+  tupToList (Tup6 x1 x2 x3 x4 x5 x6) = [x1,x2,x3,x4,x5,x6]
+  tupFromList [x1,x2,x3,x4,x5,x6] = Tup6 x1 x2 x3 x4 x5 x6
+  tupFromList _ = error "tupFromList: list should have length 6"
+
+instance Tup Tup7 where
+  tupSize _ = 7
+  tupToList (Tup7 x1 x2 x3 x4 x5 x6 x7) = [x1,x2,x3,x4,x5,x6,x7]
+  tupFromList [x1,x2,x3,x4,x5,x6,x7] = Tup7 x1 x2 x3 x4 x5 x6 x7
+  tupFromList _ = error "tupFromList: list should have length 7"
+
+instance Tup Tup8 where
+  tupSize _ = 8
+  tupToList (Tup8 x1 x2 x3 x4 x5 x6 x7 x8) = [x1,x2,x3,x4,x5,x6,x7,x8]
+  tupFromList [x1,x2,x3,x4,x5,x6,x7,x8] = Tup8 x1 x2 x3 x4 x5 x6 x7 x8
+  tupFromList _ = error "tupFromList: list should have length 8"
+
+instance Tup Tup9 where
+  tupSize _ = 9
+  tupToList (Tup9 x1 x2 x3 x4 x5 x6 x7 x8 x9) = [x1,x2,x3,x4,x5,x6,x7,x8,x9]
+  tupFromList [x1,x2,x3,x4,x5,x6,x7,x8,x9] = Tup9 x1 x2 x3 x4 x5 x6 x7 x8 x9
+  tupFromList _ = error "tupFromList: list should have length 9"
+
+--------------------------------------------------------------------------------
+
+instance Applicative Tup1 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup1 x
+  Tup1 f1 <*> Tup1 x1 = Tup1 (f1 x1)
+
+instance Applicative Tup2 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup2 x x
+  Tup2 f1 f2 <*> Tup2 x1 x2 = Tup2 (f1 x1) (f2 x2)
+
+instance Applicative Tup3 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup3 x x x
+  Tup3 f1 f2 f3 <*> Tup3 x1 x2 x3 = Tup3 (f1 x1) (f2 x2) (f3 x3)
+
+instance Applicative Tup4 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup4 x x x x
+  Tup4 f1 f2 f3 f4 <*> Tup4 x1 x2 x3 x4 = Tup4 (f1 x1) (f2 x2) (f3 x3) (f4 x4)
+
+instance Applicative Tup5 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup5 x x x x x
+  Tup5 f1 f2 f3 f4 f5 <*> Tup5 x1 x2 x3 x4 x5 = Tup5 (f1 x1) (f2 x2) (f3 x3) (f4 x4) (f5 x5)
+
+instance Applicative Tup6 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup6 x x x x x x
+  Tup6 f1 f2 f3 f4 f5 f6 <*> Tup6 x1 x2 x3 x4 x5 x6 = Tup6 (f1 x1) (f2 x2) (f3 x3) (f4 x4) (f5 x5) (f6 x6)
+
+instance Applicative Tup7 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup7 x x x x x x x
+  Tup7 f1 f2 f3 f4 f5 f6 f7 <*> Tup7 x1 x2 x3 x4 x5 x6 x7 
+    = Tup7 (f1 x1) (f2 x2) (f3 x3) (f4 x4) (f5 x5) (f6 x6) (f7 x7)
+
+instance Applicative Tup8 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup8 x x x x x x x x
+  Tup8 f1 f2 f3 f4 f5 f6 f7 f8 <*> Tup8 x1 x2 x3 x4 x5 x6 x7 x8 
+    = Tup8 (f1 x1) (f2 x2) (f3 x3) (f4 x4) (f5 x5) (f6 x6) (f7 x7) (f8 x8)
+
+instance Applicative Tup9 where
+  {-# INLINE pure  #-}
+  {-# INLINE (<*>) #-}
+  pure x = Tup9 x x x x x x x x x
+  Tup9 f1 f2 f3 f4 f5 f6 f7 f8 f9 <*> Tup9 x1 x2 x3 x4 x5 x6 x7 x8 x9 
+    = Tup9 (f1 x1) (f2 x2) (f3 x3) (f4 x4) (f5 x5) (f6 x6) (f7 x7) (f8 x8) (f9 x9)
+
+--------------------------------------------------------------------------------
+
+#define NUM_INSTANCE                   \
+  { t1 + t2 = (+) <$> t1 <*> t2        \
+  ; t1 - t2 = (-) <$> t1 <*> t2        \
+  ; t1 * t2 = (*) <$> t1 <*> t2        \
+  ; abs    = fmap abs                  \
+  ; signum = fmap signum               \
+  ; fromInteger = pure . fromInteger }
+
+instance Num a => Num (Tup1 a) where NUM_INSTANCE
+instance Num a => Num (Tup2 a) where NUM_INSTANCE
+instance Num a => Num (Tup3 a) where NUM_INSTANCE
+instance Num a => Num (Tup4 a) where NUM_INSTANCE
+instance Num a => Num (Tup5 a) where NUM_INSTANCE
+instance Num a => Num (Tup6 a) where NUM_INSTANCE
+instance Num a => Num (Tup7 a) where NUM_INSTANCE
+instance Num a => Num (Tup8 a) where NUM_INSTANCE
+instance Num a => Num (Tup9 a) where NUM_INSTANCE
+
+--------------------------------------------------------------------------------
+
+#define FRACTIONAL_INSTANCE              \
+  { t1 / t2 = (/) <$> t1 <*> t2          \
+  ; recip   = fmap recip                 \
+  ; fromRational = pure . fromRational }
+
+instance Fractional a => Fractional (Tup1 a) where FRACTIONAL_INSTANCE
+instance Fractional a => Fractional (Tup2 a) where FRACTIONAL_INSTANCE
+instance Fractional a => Fractional (Tup3 a) where FRACTIONAL_INSTANCE
+instance Fractional a => Fractional (Tup4 a) where FRACTIONAL_INSTANCE
+instance Fractional a => Fractional (Tup5 a) where FRACTIONAL_INSTANCE
+instance Fractional a => Fractional (Tup6 a) where FRACTIONAL_INSTANCE
+instance Fractional a => Fractional (Tup7 a) where FRACTIONAL_INSTANCE
+instance Fractional a => Fractional (Tup8 a) where FRACTIONAL_INSTANCE
+instance Fractional a => Fractional (Tup9 a) where FRACTIONAL_INSTANCE
+
+--------------------------------------------------------------------------------
+
+#define MONOID_INSTANCE                     \
+  { mempty = pure mempty                    \
+  ; mappend t1 t2 = mappend <$> t1 <*> t2 } 
+
+instance Monoid a => Monoid (Tup1 a) where MONOID_INSTANCE
+instance Monoid a => Monoid (Tup2 a) where MONOID_INSTANCE
+instance Monoid a => Monoid (Tup3 a) where MONOID_INSTANCE
+instance Monoid a => Monoid (Tup4 a) where MONOID_INSTANCE
+instance Monoid a => Monoid (Tup5 a) where MONOID_INSTANCE
+instance Monoid a => Monoid (Tup6 a) where MONOID_INSTANCE
+instance Monoid a => Monoid (Tup7 a) where MONOID_INSTANCE
+instance Monoid a => Monoid (Tup8 a) where MONOID_INSTANCE
+instance Monoid a => Monoid (Tup9 a) where MONOID_INSTANCE
+
+--------------------------------------------------------------------------------
+
+#define STORABLE_INSTANCE                                 \
+  { sizeOf    t = tupSize t * sizeOf (tupUndef t)         \
+  ; alignment t = alignment (tupUndef t)                  \
+  ; peek ptr    = let { ptrUndef :: Ptr b -> b ; ptrUndef _ = undefined }              \
+                  in  tupFromList <$> peekArray (tupSize $ ptrUndef ptr) (castPtr ptr) \
+  ; poke ptr t  = pokeArray (castPtr ptr) (tupToList t) }
+
+instance Storable a => Storable (Tup1 a) where STORABLE_INSTANCE
+instance Storable a => Storable (Tup2 a) where STORABLE_INSTANCE
+instance Storable a => Storable (Tup3 a) where STORABLE_INSTANCE
+instance Storable a => Storable (Tup4 a) where STORABLE_INSTANCE
+instance Storable a => Storable (Tup5 a) where STORABLE_INSTANCE
+instance Storable a => Storable (Tup6 a) where STORABLE_INSTANCE
+instance Storable a => Storable (Tup7 a) where STORABLE_INSTANCE
+instance Storable a => Storable (Tup8 a) where STORABLE_INSTANCE
+instance Storable a => Storable (Tup9 a) where STORABLE_INSTANCE
+
+--------------------------------------------------------------------------------
+ LICENSE view
@@ -0,0 +1,29 @@+Copyright (c) 2012, Balazs Komuves+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++- Redistributions of source code must retain the above copyright notice,+this list of conditions and the following disclaimer.+ +- Redistributions in binary form must reproduce the above copyright notice,+this list of conditions and the following disclaimer in the documentation+and/or other materials provided with the distribution.+ +- Neither names of the copyright holders nor the names of the contributors+may be used to endorse or promote products derived from this software without+specific prior written permission. ++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER +OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+
+ Setup.lhs view
@@ -0,0 +1,3 @@+#! /usr/bin/env runhaskell+> import Distribution.Simple+> main = defaultMain
+ preprocessor/tpp.hs view
@@ -0,0 +1,154 @@+
+-- | Tuple brackets preprocessor.
+-- Use like this:
+-- 
+-- > {-# OPTIONS -F -pgmF tuplepp #-}
+--
+-- Write code like this:
+--
+-- > x = {{a,b,c}}
+--
+-- and it will be translated to this:
+--
+-- > x = Tup3 a b c 
+-- 
+{-# LANGUAGE PackageImports #-}
+module Main where
+
+--------------------------------------------------------------------------------
+
+import Data.Char
+
+import Language.Haskell.Exts
+import "parsec2" Text.ParserCombinators.Parsec
+
+import System.Environment
+
+-- import Debug.Trace
+-- debug x = trace (show x)
+
+--------------------------------------------------------------------------------
+
+tupleCon :: Int -> Exp
+tupleCon k = Var $ UnQual $ Ident ("Tup" ++ show k)
+
+toTupleE :: Exp -> Exp
+toTupleE e = case e of
+  Tuple es -> foldl App (tupleCon (length es)) es
+  _        -> App (tupleCon 1) e
+
+inparens :: String -> String
+inparens s = "(" ++ s ++ ")"
+
+toTupleS :: String -> String
+toTupleS s = {- trace ("|"++s++"|") $ -} case parseExp (inparens s) of
+  ParseOk e -> pp (toTupleE e)
+  err       -> error ("parse error in idiom bracket:\n" ++ show err)
+
+pp :: Pretty a => a -> String
+pp = prettyPrintStyleMode style mode where
+  mode = defaultMode
+    { layout = PPNoLayout
+    }
+  style = Style 
+    { mode = LeftMode -- OneLineMode
+    , lineLength = 1000
+    , ribbonsPerLine = 1.5
+    }
+  
+--------------------------------------------------------------------------------
+
+data TupleLine 
+  = S String
+  | I TupleLine (Bool,TupleLine) TupleLine      -- pre (isTuple,bracket) post
+  deriving Show
+
+{-
+xinit :: TupleLine -> TupleLine
+xinit (S str) = S (init str)
+xinit (I pre mid post) = I pre mid (xinit post)
+
+xtail :: TupleLine -> TupleLine
+xtail (S str) = S (tail str)
+xtail (I pre mid post) = I (xtail pre) mid post
+-}
+
+lineP :: Parser TupleLine
+lineP = do
+  pre <- many (noneOf "{}")  
+  m <- optionMaybe $ do
+
+    char '{'
+    c <- lookAhead anyChar
+    mid <- case c of
+      '{' -> char '{' >> lineP
+      _   -> lineP
+
+    char '}'
+    d <- lookAhead anyChar
+    post <- case d of
+      '}' -> char '}' >> lineP
+      _   -> lineP
+
+    let b = (c=='{') && (d=='}') -- True -- if isAlphaNum c || elem c "({[_" then True else False
+
+    return (b,mid,post)
+  return $ case m of
+    Nothing -> S pre
+    Just (b,mid,post) -> case b of
+      True  -> I (S pre) (b,mid) (post)
+      False -> I (S pre) (b,mid) (post)
+
+parseLine :: SourceName -> String -> TupleLine
+parseLine src s = case runParser lineP () "" s of
+  Right xx -> xx
+  Left err -> error ("preprocessor parse error in file \"" ++ src ++ "\":\n" ++ show err)
+
+convertTupleLine :: TupleLine -> String
+convertTupleLine (S ln) = ln
+convertTupleLine (I pre (b,mid) post) = pre' ++ mid'' ++ post' where
+  pre'  = convertTupleLine pre
+  mid'  = convertTupleLine mid
+  post' = convertTupleLine post
+  mid''  = if b 
+    then '(' : toTupleS mid' ++ ")"
+    else "{" ++ mid' ++ "}"
+    
+processLine :: SourceName -> String -> String    
+processLine src = convertTupleLine . parseLine src
+    
+--------------------------------------------------------------------------------  
+
+main :: IO ()
+main = 
+  do
+    args <- getArgs
+    case args of
+
+      [] -> interact (f "stdin")
+      [inp] -> do
+        text <- readFile inp
+        putStrLn $ f inp text
+      [inp,out] -> do
+        text <- readFile inp
+        writeFile out $ f inp text
+      [inp,cpp,out] -> do             -- ghc calls the preprocessor this way
+        text <- readFile cpp
+        let pptext = f cpp text
+        writeFile out pptext
+
+      _ -> do
+        print args
+        putStrLn $ unlines
+          [ "usage:"
+          , "  tpp <input.hs >output.hs"
+          , "  tpp input.hs >output.hs"
+          , "  tpp input.hs output.hs"
+          , "  tpp dummy.hs input.hs output.hs"
+          ]
+      
+  where
+    f src text = processLine src text
+
+--------------------------------------------------------------------------------        
+
+ tup-functor.cabal view
@@ -0,0 +1,42 @@+
+Name:                tup-functor
+Version:             0.1
+Synopsis:            Homogeneous tuples
+Description:         Homogeneous tuples (also known as vectors), with various instances, most notably 'Functor' and 'Applicative'.
+                     The primary goal of the library is to help functor-oriented programming  
+                     (for low-dimensional linear algebra, there are more specific packages, eg. @vect@). 
+                     A small preprocessor for a tuple syntax is also included.
+Author:              Balazs Komuves
+license:             BSD3
+license-file:        LICENSE
+Copyright:           (c) 2012 Balazs Komuves
+Maintainer:          bkomuves (plus) hackage (at) gmail (dot) hu
+Stability:           Experimental
+Category:            System
+Tested-With:         GHC == 7.0.3
+Cabal-Version:       >= 1.6
+Build-Type:          Simple
+
+extra-source-files:  Data/Tup/Tup.inc
+  
+Library
+  Build-Depends:       base >= 3 && < 5
+
+  Exposed-Modules:     Data.Tup
+                       Data.Tup.Class
+                       Data.Tup.Strict
+                       Data.Tup.Lazy
+
+  Extensions:          CPP
+  Hs-Source-Dirs:      .
+
+  -- force-recomp is necessary since all the source code is included via the C preprocessor, 
+  -- and thus the recompilation checker is broken
+  ghc-options:         -fforce-recomp -Wall -fno-warn-unused-matches -fno-warn-unused-imports -fno-warn-unused-binds
+
+Executable tuplepp
+  Build-Depends:       base >= 3 && < 5, parsec2, haskell-src-exts  
+  Main-is:             preprocessor/tpp.hs
+  Hs-Source-Dirs:      .
+  ghc-options:         -Wall -fno-warn-unused-matches -fno-warn-unused-imports -fno-warn-unused-binds -fno-warn-unused-do-bind
+