diff --git a/ChangeLog.md b/ChangeLog.md
new file mode 100644
--- /dev/null
+++ b/ChangeLog.md
@@ -0,0 +1,6 @@
+# Revision history for polyvariadic
+
+## 0.3.0.0  -- 2017-04-19
+
+* First public version.
+
diff --git a/Data/Accumulator.hs b/Data/Accumulator.hs
new file mode 100644
--- /dev/null
+++ b/Data/Accumulator.hs
@@ -0,0 +1,59 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
+{-# LANGUAGE CPP #-}
+
+-- |
+-- Module      :  Data.Accumulator
+-- Copyright   :  (c) Francesco Gazzetta 2017
+-- License     :  BSD3 (see the file LICENSE)
+--
+-- Maintainer  :  francygazz@gmail.org
+-- Stability   :  stable
+-- Portability :  portable
+--
+-- Accumulators, primarily useful for Polyvariadic
+
+module Data.Accumulator
+  ( Accumulator (..)
+  , singleton
+  , accumulateMany
+  , AccumulatorSemigroup (..)
+  ) where
+
+import qualified Data.Set as Set
+import           Data.Foldable (foldl')
+import           Data.Semigroup
+
+#if !MIN_VERSION_base(4,8,0)
+import Data.Foldable
+#endif
+
+-- | An 'Accumulator c i' supports accumulation of elements of type i in it.
+-- This is different from 'Semigroup' or 'Monoid', where '<>' acts between
+-- two values with the same type.
+class Accumulator acc x where
+  accumulate :: x -> acc -> acc -- ^ Accumulate a value
+
+-- | Accumulate a single value in a 'Monoid'
+singleton :: (Accumulator acc x, Monoid acc) => x -> acc
+singleton = flip accumulate mempty
+
+-- | Strictly accumulate multiple values from a 'Foldable', from left to right
+accumulateMany :: (Foldable f, Accumulator acc x) => f x -> acc -> acc
+accumulateMany xs acc = foldl' (flip accumulate) acc xs
+
+instance Accumulator [a] a where
+  accumulate = (:)
+
+instance Ord a => Accumulator (Set.Set a) a where
+  accumulate = Set.insert
+
+instance Semigroup m => Accumulator (AccumulatorSemigroup m) (AccumulatorSemigroup m) where
+  accumulate = (<>)
+
+-- | Lift a 'Semigroup' into an Accumulator. This is a newtype because (<>) isn't always the ideal way of accumulating
+newtype AccumulatorSemigroup a = AccumulatorSemigroup {getAccumulatorSemigroup :: a}
+
+instance Semigroup m => Semigroup (AccumulatorSemigroup m) where
+  (<>) (AccumulatorSemigroup a) (AccumulatorSemigroup b) = AccumulatorSemigroup $ (<>) a b
+
diff --git a/Data/Function/Polyvariadic.hs b/Data/Function/Polyvariadic.hs
new file mode 100644
--- /dev/null
+++ b/Data/Function/Polyvariadic.hs
@@ -0,0 +1,110 @@
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+-- |
+-- Module      :  Data.Function.Polyvariadic
+-- Copyright   :  (c) Francesco Gazzetta 2017
+-- License     :  BSD3 (see the file LICENSE)
+--
+-- Maintainer  :  francygazz@gmail.org
+-- Stability   :  experimental
+-- Portability :  portable
+--
+-- Create and apply functions with an arbitrary number of arguments.
+
+module Data.Function.Polyvariadic
+  ( -- * Creation
+    Polyvariadic (..)
+    -- * Application
+  , Apply (apply')
+  , apply
+  ) where
+
+import Data.Foldable
+import Data.Accumulator
+
+
+---- creation
+
+-- | Creation of functions with an arbitrary number of arguments.
+--
+-- The arguments will be accumulated in the given 'Accumulator',
+-- which will then be passed as an argument to the function.
+--
+-- ==== __Examples__
+--
+-- Three integers to a list. Note that you have to add type annotations
+-- for nearly everything to avoid ambiguities
+-- >>> polyvariadic mempty (id :: [Int] -> [Int]) (1::Int) (2::Int) (3::Int) :: [Int]
+--
+-- The classic @printf@ function, which takes an arbitrary amount of arguments
+-- and inserts them in a string:
+--
+-- @
+-- {-# LANGUAGE MultiParamTypeClasses #-}
+-- {-# LANGUAGE FlexibleInstances #-}
+-- {-# LANGUAGE FlexibleContexts #-}
+-- import Data.Function.Polyvariadic
+-- import Data.Accumulator
+--
+-- magicChar = \'%\'
+-- notMagicChar = (\/= magicChar)
+--
+-- data PrintfAccum = PrintfAccum { done :: String, todo :: String }
+--
+-- instance Show x => Accumulator PrintfAccum x where
+--   accumulate x (PrintfAccum done (_:todo)) = PrintfAccum
+--                                               (done ++ show x ++ takeWhile notMagicChar todo)
+--                                               (dropWhile notMagicChar todo)
+--   accumulate _ acc = acc
+--
+-- printf' str = polyvariadic
+--                (PrintfAccum (takeWhile notMagicChar str) (dropWhile notMagicChar str))
+--                done
+-- @
+--
+-- >>> printf' "aaa%bbb%ccc%ddd" "TEST" 123 True
+-- "aaa\"TEST\"bbb123cccTrueddd"
+class Polyvariadic accumulator result x where
+  -- | Takes an accumulator @acc@, a function @f@, and an arbitrary
+  -- number of additional arguments which will be accumulated in @acc@,
+  -- which is finally passed to @f@.
+  polyvariadic :: accumulator -> (accumulator -> result) -> x
+
+-- | Accumulates the next argument
+instance (Accumulator c i, Polyvariadic c b x) => Polyvariadic c b (i -> x) where
+  polyvariadic a f x = polyvariadic (accumulate x a) f
+
+-- | There are no more arguments to accumulate so the function is applied
+-- to the 'Accumulator'
+instance Polyvariadic accumulator result result where
+  polyvariadic a f = f a
+
+
+---- application
+
+-- | Application of function with an arbitrary number of arguments to the
+-- elements of a list.
+--
+-- __Will raise an error if the list doesn't have enough elements__
+--
+-- ==== __Examples__
+--
+-- >>> apply ((+) :: Int -> Int -> Int) ([1,2] :: [Int]) :: Int
+-- 3
+class Apply a b x where
+  apply' :: x -> [a] -> b
+
+-- | The final type is not reached yet and the application continues
+instance (Apply a b x) => Apply a b (a -> x) where
+  apply' f (x:xs) = apply (f x) xs
+  apply' _ _ = error "Not enough arguments in polyvariadic application"
+
+-- | The final type is reached and the application terminates
+instance Apply a b b where
+  apply' f _ = f
+
+-- | Like 'apply'' but with an arbitrary 'Foldable' instead if a list
+apply :: (Apply a b x, Foldable t) => x -> t a -> b
+apply f = apply f . toList
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2017, Francesco Gazzetta
+
+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 the name of Francesco Gazzetta nor the names of other
+      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.
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/polyvariadic.cabal b/polyvariadic.cabal
new file mode 100644
--- /dev/null
+++ b/polyvariadic.cabal
@@ -0,0 +1,34 @@
+-- Initial polyvariadic.cabal generated by cabal init.  For further 
+-- documentation, see http://haskell.org/cabal/users-guide/
+
+name:                polyvariadic
+version:             0.3.0.0
+synopsis:            Creation and application of polyvariadic functions
+description:         Creation and application of polyvariadic functions, see the docs for usage and examples
+homepage:            https://github.com/fgaz/polyvariadic
+license:             BSD3
+license-file:        LICENSE
+author:              Francesco Gazzetta
+maintainer:          francygazz@gmail.com
+copyright:           (C) Francesco Gazzetta 2017
+category:            Data
+build-type:          Simple
+extra-source-files:  ChangeLog.md
+cabal-version:       >=1.10
+
+source-repository head
+  type:     git
+  location: git://github.com/fgaz/polyvariadic.git
+
+library
+  exposed-modules:     Data.Accumulator, Data.Function.Polyvariadic
+  -- other-modules:       
+  other-extensions:    MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, GeneralizedNewtypeDeriving
+  build-depends:       base >=4.7 && <4.10
+                     , containers >=0.1 && <0.6
+  if !impl(ghc >= 8.0)
+    build-depends: semigroups == 0.18.*
+  -- hs-source-dirs:      
+  default-language:    Haskell2010
+  ghc-options:         -Wall
+
