diff --git a/Data/Histogram.hs b/Data/Histogram.hs
new file mode 100644
--- /dev/null
+++ b/Data/Histogram.hs
@@ -0,0 +1,129 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE TypeOperators #-}
+-- |
+-- Module     : Data.Histogram
+-- Copyright  : Copyright (c) 2009, Alexey Khudyakov <alexey.skladnoy@gmail.com>
+-- License    : BSD3
+-- Maintainer : Alexey Khudyakov <alexey.skladnoy@gmail.com>
+-- Stability  : experimental
+-- 
+-- Immutable histograms. 
+
+module Data.Histogram ( -- * Immutable histogram
+                        Histogram(..)
+                      , module Data.Histogram.Bin
+                      , mapHist
+                      , histBin
+                      , histData
+                      , underflows
+                      , overflows
+                      , outOfRange
+                      , readHistogram
+                      -- * Conversion
+                      , asList
+                      , asPairVector
+                      , asVectorPairs
+                      -- * Slicing
+                      , sliceY
+                      , sliceX
+                      ) where
+
+import Control.Arrow ((***))
+import Control.Monad (ap)
+import Data.Array.Vector
+import Text.Read
+import Text.ParserCombinators.ReadPrec (readPrec_to_S)
+
+import Data.Histogram.Bin
+import Data.Histogram.Parse
+
+
+-- | Immutable histogram. Histogram consists of binning algorithm,
+--   optional number of under and overflows, and data. 
+data Histogram bin a where
+    Histogram :: (Bin bin, UA a) => 
+                 bin
+              -> Maybe (a,a)
+              -> UArr a
+              -> Histogram bin a
+
+
+instance (Show a, Show (BinValue bin), Show bin) => Show (Histogram bin a) where
+    show h@(Histogram bin uo _) = "# Histogram\n" ++ showUO uo ++ show bin ++
+                                  (unlines $ map showT $ asList h)
+        where
+          showT (x,y) = show x ++ "\t" ++ show y
+          showUO (Just (u,o)) = "# Underflows = " ++ show u ++ "\n" ++
+                                "# Overflows  = " ++ show o ++ "\n"
+          showUO Nothing      = "# Underflows = \n" ++
+                                "# Overflows  = \n"
+
+histHeader :: (Read bin, Read a, Bin bin, UA a) => ReadPrec (UArr a -> Histogram bin a)
+histHeader = do
+  keyword "Histogram"
+  u   <- maybeValue "Underflows"
+  o   <- maybeValue "Overflows"
+  bin <- readPrec
+  return $ Histogram bin ((,) `fmap` u `ap` o)
+
+-- | Convert String to histogram. Histogram do not have Read instance
+--   because of slowness of ReadP
+readHistogram :: (Read bin, Read a, Bin bin, UA a) => String -> Histogram bin a
+readHistogram str = 
+    let [(h,rest)] = readPrec_to_S histHeader 0 str 
+        xs = map last . filter (not . null) . map words . lines $ rest
+    in h (toU $ map read xs)
+
+-- | fmap lookalike. It's not possible to create Functor instance
+--   because of UA restriction.
+mapHist :: UA b => (a -> b) -> Histogram bin a -> Histogram bin b
+mapHist f (Histogram bin uo a) = Histogram bin (fmap (f *** f) uo) (mapU f a)
+
+-- | Histogram bins
+histBin :: Histogram bin a -> bin
+histBin (Histogram bin _ _) = bin
+
+-- | Histogram data as vector
+histData :: Histogram bin a -> UArr a
+histData (Histogram _ _ a) = a
+
+-- | Number of underflows
+underflows :: Histogram bin a -> Maybe a
+underflows (Histogram _ uo _) = fmap fst uo
+
+-- | Number of overflows
+overflows :: Histogram bin a -> Maybe a
+overflows (Histogram _ uo _) = fmap snd uo
+
+-- | Underflows and overflows
+outOfRange :: Histogram bin a -> Maybe (a,a)
+outOfRange (Histogram _ uo _) = uo
+
+-- | Convert histogram to list.
+asList :: Histogram bin a -> [(BinValue bin, a)]
+asList (Histogram bin _ arr) = map (fromIndex bin) [0..] `zip` fromU arr
+
+-- | Convert to pair of vectors
+asPairVector :: UA (BinValue bin) => Histogram bin a -> (UArr (BinValue bin), UArr a)
+asPairVector (Histogram bin _ a) = (toU $ map (fromIndex bin) [0 .. nBins bin], a)
+
+-- | Convert to vector of pairs
+asVectorPairs :: UA (BinValue bin) => Histogram bin a -> UArr ((BinValue bin) :*: a)
+asVectorPairs h@(Histogram _ _ _) = uncurry zipU . asPairVector $ h
+
+-- | Slice 2D histogram along Y axis. This function is fast because it does not require reallocations.
+sliceY :: (Bin bX, Bin bY) => Histogram (Bin2D bX bY) a -> [(BinValue bY, Histogram bX a)]
+sliceY (Histogram b@(Bin2D bX _) _ a) = map mkHist $ init [0, nBins bX .. nBins b]
+    where
+      mkHist i = ( snd $ fromIndex b i
+                 , Histogram bX Nothing (sliceU a i (nBins bX)) )
+
+-- | Slice 2D histogram along X axis.
+sliceX :: (Bin bX, Bin bY) => Histogram (Bin2D bX bY) a -> [(BinValue bX, Histogram bY a)]
+sliceX (Histogram b@(Bin2D bX bY) _ a) = map mkHist $ init [0 .. nx]
+    where
+      nx = nBins bX
+      n  = nBins b
+      mkHist i = ( fst $ fromIndex b i
+                 , Histogram bY Nothing (toU $ map (indexU a) [i,i+nx .. n-1]) )
diff --git a/Data/Histogram/Bin.hs b/Data/Histogram/Bin.hs
new file mode 100644
--- /dev/null
+++ b/Data/Histogram/Bin.hs
@@ -0,0 +1,162 @@
+{-# LANGUAGE GADTs        #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE BangPatterns #-}
+-- |
+-- Module     : Data.Histogram.Bin
+-- Copyright  : Copyright (c) 2009, Alexey Khudyakov <alexey.skladnoy@gmail.com>
+-- License    : BSD3
+-- Maintainer : Alexey Khudyakov <alexey.skladnoy@gmail.com>
+-- Stability  : experimental
+-- 
+-- Binning algorithms. This is mapping from set of interest to integer
+-- indices and approximate reverse. 
+
+module Data.Histogram.Bin ( -- * Type class
+                            Bin(..)
+                          -- * Integer bins
+                          , BinI(..)
+                          -- * Floating point bins
+                          , BinF
+                          , binF
+                          , binFn
+                          -- * 2D bins
+                          , Bin2D(..)
+                          , (><)
+                          ) where
+
+import Data.Histogram.Parse
+import Text.Read (Read(..))
+
+
+
+-- | Abstract binning algorithm. Following invariant is expected to hold: 
+-- 
+-- > toIndex . fromIndex == id
+-- 
+-- Reverse is not nessearily true. 
+class Bin b where
+    -- | Type of value to bin
+    type BinValue b
+    -- | Convert from value to index. No bound checking performed
+    toIndex :: b -> BinValue b -> Int
+    {-# INLINE toIndex #-}
+    -- | Convert from index to value. 
+    fromIndex :: b -> Int -> BinValue b 
+    -- | Total number of bins
+    nBins :: b -> Int
+
+
+----------------------------------------------------------------
+-- Integer bin
+
+-- | Integer bins. This is inclusive interval [from,to]
+data BinI = BinI !Int !Int
+
+instance Bin BinI where
+    type BinValue BinI = Int
+    toIndex   !(BinI base _) !x = x - base
+    fromIndex !(BinI base _) !x = x + base
+    nBins     !(BinI x y) = y - x + 1
+
+instance Show BinI where
+    show (BinI lo hi) = unlines [ "# BinI"
+                                , "# Low  = " ++ show lo
+                                , "# High = " ++ show hi
+                                ]
+
+instance Read BinI where
+    readPrec = do
+      keyword "BinI"
+      l <- value "Low"
+      h <- value "High"
+      return $ BinI l h
+
+
+----------------------------------------------------------------
+-- Floating point bin
+
+-- | Floaintg point bins with equal sizes.
+data BinF f where
+    BinF :: RealFrac f => !f -> !f -> !Int -> BinF f 
+
+-- | Create bins 
+binF :: RealFrac f => 
+        f   -- ^ Lower bound of range
+     -> Int -- ^ Number of bins
+     -> f   -- ^ Upper bound of range
+     -> BinF f
+binF from n to = BinF from ((to - from) / fromIntegral n) n
+
+-- | Create bins. Note that actual upper bound can differ from specified.
+binFn :: RealFrac f =>
+         f -- ^ Begin of range
+      -> f -- ^ Size of step
+      -> f -- ^ Approximation of end of range
+      -> BinF f 
+binFn from step to = BinF from step (round $ (to - from) / step)
+
+instance Bin (BinF f) where
+    type BinValue (BinF f) = f 
+    toIndex   !(BinF from step _) !x = floor $ (x-from) / step
+    fromIndex !(BinF from step _) !i = (step/2) + (fromIntegral i * step) + from 
+    nBins     !(BinF _ _ n) = n
+    {-# SPECIALIZE instance Bin (BinF Double) #-}
+    {-# SPECIALIZE instance Bin (BinF Float) #-}
+
+instance Show f => Show (BinF f) where
+    show (BinF base step n) = unlines [ "# BinF"
+                                  , "# Base = " ++ show base
+                                  , "# Step = " ++ show step
+                                  , "# N    = " ++ show n
+                                  ]
+
+instance (Read f, RealFrac f) => Read (BinF f) where
+    readPrec = do
+      keyword "BinF"
+      base <- value "Base"
+      step <- value "Step"
+      n    <- value "N"
+      return $ BinF base step n
+
+
+----------------------------------------------------------------
+-- 2D bin
+
+-- | 2D bins. bin1 is binning along X axis and bin2 is one along Y axis. 
+data Bin2D bin1 bin2 = Bin2D bin1 bin2
+
+-- | Alias for 'Bin2D'.
+(><) :: bin1 -> bin2 -> Bin2D bin1 bin2
+(><) = Bin2D
+
+instance (Bin bin1, Bin bin2) => Bin (Bin2D bin1 bin2) where
+    type BinValue (Bin2D bin1 bin2) = (BinValue bin1, BinValue bin2)
+
+    toIndex   (Bin2D bx by) (x,y) 
+        | ix < 0 || ix >= rx || iy < 0 || iy >= ry = maxBound
+        | otherwise                                = ix + iy*rx
+        where
+          ix = toIndex bx x
+          iy = toIndex by y
+          rx = nBins bx
+          ry = nBins by
+
+    fromIndex (Bin2D bx by) i = let (iy,ix) = divMod i (nBins bx)
+                                in  (fromIndex bx ix, fromIndex by iy)
+
+    nBins (Bin2D b1 b2) = (nBins b1) * (nBins b2)
+
+instance (Show b1, Show b2) => Show (Bin2D b1 b2) where
+    show (Bin2D b1 b2) = "# Bin2D\n" ++
+                         "# X\n" ++ 
+                         show b1 ++
+                         "# Y\n" ++
+                         show b2
+instance (Read b1, Read b2) => Read (Bin2D b1 b2) where
+    readPrec = do
+      keyword "Bin2D"
+      keyword "X"
+      b1 <- readPrec
+      keyword "Y"
+      b2 <- readPrec
+      return $ Bin2D b1 b2
diff --git a/Data/Histogram/Fill.hs b/Data/Histogram/Fill.hs
new file mode 100644
--- /dev/null
+++ b/Data/Histogram/Fill.hs
@@ -0,0 +1,188 @@
+{-# LANGUAGE GADTs        #-}
+{-# LANGUAGE Rank2Types   #-}
+-- |
+-- Module     : Data.Histogram.Fill
+-- Copyright  : Copyright (c) 2009, Alexey Khudyakov <alexey.skladnoy@gmail.com>
+-- License    : BSD3
+-- Maintainer : Alexey Khudyakov <alexey.skladnoy@gmail.com>
+-- Stability  : experimental
+-- 
+-- Module with algorithms for histogram filling. This is pure wrapper
+-- around stateful histograms.
+-- 
+module Data.Histogram.Fill ( -- * Type classes & wrappers
+                             HBuilderCl(..)
+                           , HBuilder
+                           , builderList
+                           , builderListWrap
+
+                           -- * Fill routines
+                           , createHistograms
+
+                           -- * Histogram constructors 
+                           , module Data.Histogram.Bin
+                           , mkHist
+                           , mkHist1
+                           , mkHistWgh
+                           , mkHistWgh1
+                           , mkHistMonoid
+                           , mkHistMonoid1
+                           , forceInt
+                           , forceDouble
+                           , forceFloat
+                           -- * Internals
+                           , HistBuilder
+                           ) where
+
+import Control.Monad.ST (ST)
+import Data.Monoid      (Monoid, mempty)
+
+import Data.Array.Vector
+import Data.Histogram
+import Data.Histogram.Bin
+import Data.Histogram.ST
+
+----------------------------------------------------------------
+
+-- | Create and fill histogram(s).
+createHistograms :: Monoid b =>
+                    HBuilder a b -- ^ Instructions how to fill histograms
+                 -> [a]          -- ^ List of data to fill histogram with
+                 -> b            -- ^ Result
+createHistograms h xs = fillHistograms (runBuilder h) xs
+
+----------------------------------------------------------------
+
+-- | Histogram builder typeclass. Instance of this class contain
+--   instructions how to build histograms.
+class HBuilderCl h where 
+    -- | Convert input type of histogram from a to a'
+    modifyIn  :: (a' -> a) -> h a b -> h a' b 
+    -- | Convert output of histogram 
+    modifyOut :: (b -> b') -> h a b -> h a  b'
+    -- | Create stateful histogram from instructions. Histograms could
+    --   be filled either in the ST monad or with createHistograms
+    runBuilder :: h a b -> ST s (Accum s a b)
+
+
+----------------------------------------------------------------
+
+-- | Abstract histogram builder. All real builders should be wrapper
+--   in this type
+data HBuilder a b where
+    MkHBuilder :: HBuilderCl h => h a b -> HBuilder a b
+
+instance HBuilderCl HBuilder where 
+    modifyIn  f (MkHBuilder h) = MkHBuilder $ modifyIn f h
+    modifyOut g (MkHBuilder h) = MkHBuilder $ modifyOut g h 
+    runBuilder  (MkHBuilder h) = runBuilder h
+
+
+----------------------------------------------------------------
+
+-- List of histograms. 
+newtype HBuilderList a b = HBuilderList [HBuilder a b]
+
+-- | Wrap list of histogram builders into HBuilder.
+builderList :: [HBuilder a b] -> HBuilder a [b]
+builderList = MkHBuilder . modifyOut (:[]) . HBuilderList
+
+-- | Wrap list of histogram builders into HBuilder and do not change return type.
+builderListWrap :: [HBuilder a b] -> HBuilder a b
+builderListWrap = MkHBuilder . HBuilderList
+
+instance HBuilderCl HBuilderList where
+    modifyIn  f (HBuilderList l) = HBuilderList $ map (modifyIn f) l
+    modifyOut g (HBuilderList l) = HBuilderList $ map (modifyOut g) l
+    runBuilder (HBuilderList l)  = accumList $ map runBuilder l
+
+----------------------------------------------------------------
+
+-- | Generic histogram builder. 
+data HistBuilder a b where
+    HistBuilder :: (Bin bin, UA val) =>
+                   bin                                                -- Bin type
+                -> val                                                -- Zero element
+                -> (forall s . a -> HistogramST s bin val -> ST s ()) -- Input function
+                -> (Histogram bin val -> b)                           -- Output function
+                -> HistBuilder a b
+
+instance HBuilderCl HistBuilder where
+    modifyIn  f (HistBuilder bin z inp out) = HistBuilder bin z (inp . f) out
+    modifyOut g (HistBuilder bin z inp out) = HistBuilder bin z  inp (g . out)
+    runBuilder  (HistBuilder bin z inp out) = accumHist inp out =<< newHistogramST z bin
+
+
+
+----------------------------------------------------------------
+-- Histogram constructors 
+----------------------------------------------------------------
+
+-- | Function used to restrict type of histrogram.
+forceInt :: Histogram bin Int -> Histogram bin Int
+forceInt = id
+
+-- | Function used to restrict type of histrogram.
+forceDouble :: Histogram bin Double -> Histogram bin Double
+forceDouble = id
+
+-- | Function used to restrict type of histrogram.
+forceFloat :: Histogram bin Float -> Histogram bin Float
+forceFloat = id
+
+-- | Create histogram builder which take single item as input. Each
+--   item has weight 1. To set type of bin 'force*' function could be used.
+mkHist1 :: (Bin bin, UA val, Num val) =>
+           bin                      -- ^ Bin information
+        -> (Histogram bin val -> b) -- ^ Output function 
+        -> (a -> BinValue bin)      -- ^ Input function
+        -> HBuilder a b
+mkHist1 bin out inp = MkHBuilder $ HistBuilder bin 0 (flip fillOne . inp) out
+
+-- | Create histogram builder which take many items as input. Each
+--   item has weight 1. To set type of bin 'force*' function could be
+--   used.
+mkHist :: (Bin bin, UA val, Num val) =>
+          bin                      -- ^ Bin information
+       -> (Histogram bin val -> b) -- ^ Output function
+       -> (a -> [BinValue bin])    -- ^ Input function 
+       -> HBuilder a b
+mkHist bin out inp = MkHBuilder $ HistBuilder bin 0 fill out
+    where
+      fill a h = mapM_ (fillOne h) $ inp a
+
+-- | Create histogram with weighted bin. Takes one item at time. 
+mkHistWgh1 :: (Bin bin, UA val, Num val) =>
+              bin                        -- ^ Bin information
+          -> (Histogram bin val -> b)    -- ^ Output function
+          -> (a -> (BinValue bin, val))  -- ^ Input function
+          -> HBuilder a b
+mkHistWgh1 bin out inp = MkHBuilder $ HistBuilder bin 0 (flip fillOneW . inp) out
+
+-- | Create histogram with weighted bin. Takes many items at time.
+mkHistWgh :: (Bin bin, UA val, Num val) => 
+             bin                          -- ^ Bin information
+          -> (Histogram bin val  -> b)    -- ^ Output function
+          -> (a -> [(BinValue bin, val)]) -- ^ Input function
+          -> HBuilder a b
+mkHistWgh bin out inp = MkHBuilder $ HistBuilder bin 0 fill out
+    where
+      fill a h = mapM_ (fillOneW h) $ inp a
+
+-- | Create histogram with monoidal bins
+mkHistMonoid1 :: (Bin bin, UA val, Monoid val) =>
+              bin                         -- ^ Bin information
+          -> (Histogram bin val -> b)     -- ^ Output function
+          -> (a -> (BinValue bin, val))   -- ^ Input function
+          -> HBuilder a b
+mkHistMonoid1 bin out inp = MkHBuilder $ HistBuilder bin mempty (flip fillMonoid . inp) out
+
+-- | Create histogram with monoidal bins. Takes many items at time.
+mkHistMonoid :: (Bin bin, UA val, Monoid val) =>
+              bin                         -- ^ Bin information
+          -> (Histogram bin val -> b)     -- ^ Output function
+          -> (a -> [(BinValue bin, val)]) -- ^ Input function
+          -> HBuilder a b
+mkHistMonoid bin out inp = MkHBuilder $ HistBuilder bin mempty fill out
+    where
+      fill a h = mapM_ (fillMonoid h) $ inp a
diff --git a/Data/Histogram/Parse.hs b/Data/Histogram/Parse.hs
new file mode 100644
--- /dev/null
+++ b/Data/Histogram/Parse.hs
@@ -0,0 +1,46 @@
+module Data.Histogram.Parse ( ws
+                            , eol
+                            , value
+                            , maybeValue
+                            , keyword
+                            ) where
+
+import Text.Read
+import Text.ParserCombinators.ReadP    (ReadP, many, satisfy, char, string)
+import Text.ParserCombinators.ReadPrec
+
+-- Whitespaces
+ws :: ReadP String
+ws = many $ satisfy (`elem` " \t")
+
+-- End of line
+eol :: ReadP Char
+eol = char '\n'
+
+-- Equal sign
+eq :: ReadP ()
+eq = ws >> char '=' >> return ()
+
+-- Key
+key :: String -> ReadP String
+key s = char '#' >> ws >> string s 
+
+
+getVal :: Read a => ReadPrec a
+getVal = do x <- readPrec
+            lift eol 
+            return x
+
+-- Key value pair
+value :: Read a => String -> ReadPrec a
+value str = do lift $ key str >> eq
+               getVal
+
+-- Return optional value
+maybeValue :: Read a => String -> ReadPrec (Maybe a)
+maybeValue str = do lift $ key str >> eq
+                    (lift $ ws >> eol >> return Nothing) <++ (Just `fmap` getVal)
+
+-- Keyword
+keyword :: String -> ReadPrec ()
+keyword str = lift $ key str >> ws >> eol >> return ()
diff --git a/Data/Histogram/ST.hs b/Data/Histogram/ST.hs
new file mode 100644
--- /dev/null
+++ b/Data/Histogram/ST.hs
@@ -0,0 +1,170 @@
+{-# LANGUAGE GADTs #-}
+{-# LANGUAGE BangPatterns #-}
+{-# LANGUAGE Rank2Types #-}
+-- |
+-- Module     : Data.Histogram.ST
+-- Copyright  : Copyright (c) 2009, Alexey Khudyakov <alexey.skladnoy@gmail.com>
+-- License    : BSD3
+-- Maintainer : Alexey Khudyakov <alexey.skladnoy@gmail.com>
+-- Stability  : experimental
+-- 
+-- Mutable histograms.
+
+module Data.Histogram.ST ( -- * Mutable histograms
+                           HistogramST(..)
+                         , newHistogramST
+                         , fillOne
+                         , fillOneW
+                         , fillMonoid
+                         , freezeHist
+
+                         -- * Accumulators
+                         , Accumulator(..)
+                         , Accum(Accum)
+
+                         , accumList
+                         , accumHist
+
+                         , fillHistograms
+                         ) where
+
+
+import Control.Monad.ST
+
+import Data.Array.Vector
+import Data.Monoid
+
+import Data.Histogram
+import Data.Histogram.Bin
+
+
+----------------------------------------------------------------
+-- Mutable histograms
+----------------------------------------------------------------
+
+-- | Mutable histogram.
+data HistogramST s bin a where
+    HistogramST :: (Bin bin, UA a) => 
+                   bin
+                -> MUArr a s -- Over/underflows
+                -> MUArr a s -- Data
+                -> HistogramST s bin a
+
+-- | Create new mutable histogram. All bins are set to zero element as
+--   passed to function.
+newHistogramST :: (Bin bin, UA a) => a -> bin -> ST s (HistogramST s bin a)
+newHistogramST zero bin = do
+  uo <- newMU 2
+  writeMU uo 0 zero >> writeMU uo 1 zero
+  a <- newMU (nBins bin)
+  mapM_ (\i -> writeMU a i zero) [0 .. (lengthMU a) - 1]
+  return $ HistogramST bin uo a
+
+-- | Put one value into histogram
+fillOne :: Num a => HistogramST s bin a -> BinValue bin -> ST s ()
+fillOne (HistogramST bin uo arr) x
+    | i < 0             = writeMU uo  0 . (+1)  =<< readMU uo 0
+    | i >= lengthMU arr = writeMU uo  1 . (+1)  =<< readMU uo 1
+    | otherwise         = writeMU arr i . (+1)  =<< readMU arr i
+    where
+      i = toIndex bin x
+
+-- | Put one value into histogram with weight
+fillOneW :: Num a => HistogramST s bin a -> (BinValue bin, a) -> ST s ()
+fillOneW (HistogramST bin uo arr) (x,w)
+    | i < 0             = writeMU uo  0 . (+w)  =<< readMU uo 0
+    | i >= lengthMU arr = writeMU uo  1 . (+w)  =<< readMU uo 1
+    | otherwise         = writeMU arr i . (+w)  =<< readMU arr i
+    where
+      i = toIndex bin x
+
+-- | Put one monoidal element
+fillMonoid :: Monoid a => HistogramST s bin a -> (BinValue bin, a) -> ST s ()
+fillMonoid (HistogramST bin uo arr) (x,m)
+    | i < 0             = writeMU uo  1 . (flip mappend m)  =<< readMU uo  0
+    | i >= lengthMU arr = writeMU uo  1 . (flip mappend m)  =<< readMU uo  1
+    | otherwise         = writeMU arr i . (flip mappend m)  =<< readMU arr i
+    where
+      i = toIndex bin x
+
+-- | Create immutable histogram from mutable one. This operation involve copying.
+freezeHist :: HistogramST s bin a -> ST s (Histogram bin a)
+freezeHist (HistogramST bin uo arr) = do
+  [u,o] <- fromU `fmap` unsafeFreezeAllMU uo -- Is it safe???
+  -- Copy array
+  let len = lengthMU arr
+  tmp  <- newMU len
+  memcpyOffMU arr tmp 0 0 len
+  a    <- unsafeFreezeAllMU tmp
+  return $ Histogram bin (Just (u,o)) a
+
+
+
+----------------------------------------------------------------
+-- Accumulator typeclass
+----------------------------------------------------------------
+-- | This is class with accumulation semantics. It's used to fill many
+--   histogram at once. It accept values of type a and return data of type b.
+class Accumulator h where
+    -- | Put one element into accumulator
+    putOne  :: h s a b -> a   -> ST s () 
+    -- | Extract data from historam
+    extract :: Monoid b => (h s a b) -> ST s b
+
+-- | Put many elements in histogram(s) at once 
+putMany :: Accumulator h => h s a b -> [a] -> ST s () 
+putMany !h = mapM_ (putOne h) 
+
+-- | Put all values into histogram and return result
+fillHistograms :: Monoid b => (forall s . ST s (Accum s a b)) -> [a] -> b
+fillHistograms h xs = runST $ do h' <- h
+                                 putMany h' xs
+                                 extract h'
+
+----------------------------------------------------------------
+-- GADT wrapper 
+----------------------------------------------------------------
+-- | Abstract wrapper for histograms. 
+data Accum s a b where
+    Accum :: Accumulator h => h s a b -> Accum s a b
+
+instance Accumulator Accum where
+    putOne  !(Accum h) !x = putOne h x 
+    extract !(Accum h)    = extract h
+
+
+----------------------------------------------------------------
+-- List of histograms
+----------------------------------------------------------------
+newtype AccumList s a b = AccumList [Accum s a b]
+ 
+-- | Wrap list of histograms into one 'Accum'
+accumList :: [ST s (Accum s a b)] -> ST s (Accum s a b)
+accumList l = (Accum . AccumList) `fmap` sequence l
+
+instance Accumulator AccumList where
+    putOne  !(AccumList l) !x = mapM_ (flip putOne $ x) l 
+    extract !(AccumList l)    = mconcat `fmap` mapM extract l 
+
+
+----------------------------------------------------------------
+-- Generic histogram 
+----------------------------------------------------------------
+data AccumHist s a b where
+    AccumHist :: (Bin bin) =>
+                 (a -> HistogramST s bin val -> ST s ())
+              -> (Histogram bin val -> b)
+              -> HistogramST s bin val
+              -> AccumHist s a b
+
+-- | Accumulator for arbitrary 'HistogramST' based histogram
+accumHist :: (Bin bin) =>
+             (a -> HistogramST s bin val -> ST s ())
+          -> (Histogram bin val -> b)
+          -> HistogramST s bin val
+          -> ST s (Accum s a b)
+accumHist inp out h = return . Accum $ AccumHist inp out h
+
+instance Accumulator AccumHist where
+    putOne  !(AccumHist inp _ st) !x = inp x st
+    extract !(AccumHist _ out st)    = out `fmap` freezeHist st
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,2 @@
+import Distribution.Simple
+main = defaultMain
diff --git a/histogram-fill.cabal b/histogram-fill.cabal
new file mode 100644
--- /dev/null
+++ b/histogram-fill.cabal
@@ -0,0 +1,26 @@
+Name:           histogram-fill
+Version:        0.1.0
+Cabal-Version:  >= 1.2
+License:        BSD3
+License-File:   LICENSE
+Author:         Alexey Khudyakov
+Maintainer:     Alexey Khudyakov <alexey.skladnoy@gmail.com>
+Homepage:       http://bitbucket.org/Shimuuar/histogram-fill/
+Category:       Data
+Build-Type:     Simple
+Synopsis:       Library for histograms creation.
+Description:    
+  This is library for histograms filling. Its aim to provide
+  convenient way to create and fill histograms. 
+  .
+  This is very much work in progress so expect API breakage in future relesases.
+
+
+Library
+  Build-Depends:        base >=3 && <5, uvector >=0.1 && <0.2
+  Exposed-modules:      Data.Histogram
+                        Data.Histogram.Fill 
+                        Data.Histogram.Bin
+                        Data.Histogram.ST
+  Other-modules:        Data.Histogram.Parse
+  Ghc-options:          -O2 -Wall -auto-all
