diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2017 Donnacha Oisín Kidney
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
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/src/Control/Monad/Weighted.hs b/src/Control/Monad/Weighted.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Monad/Weighted.hs
@@ -0,0 +1,95 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE MultiParamTypeClasses      #-}
+{-# LANGUAGE PatternSynonyms            #-}
+{-# LANGUAGE ViewPatterns               #-}
+
+module Control.Monad.Weighted
+  (WeightedT
+  ,runWeightedT
+  ,pattern WeightedT
+  ,Weighted
+  ,runWeighted
+  ,pattern Weighted
+  ,execWeightedT
+  ,evalWeightedT
+  ,execWeighted
+  ,evalWeighted)
+  where
+
+import           Control.Applicative
+import           Control.Monad.Identity
+import           Control.Monad.State.Strict
+import           Control.Monad.Writer.Class
+import           Data.Coerce
+import           Data.Semiring
+
+-- | A monad transformer similar to 'WriterT', except that it does not leak
+-- space, and it uses the 'Semiring' class, rather than 'Monoid'.
+newtype WeightedT s m a =
+    WeightedT_ (StateT s m a)
+    deriving (Functor,Applicative,Monad,MonadTrans)
+
+runWeightedT
+    :: Semiring s
+    => WeightedT s m a -> m (a, s)
+runWeightedT =
+    (coerce :: (StateT s m a -> m (a, s)) -> WeightedT s m a -> m (a, s))
+        (`runStateT` one)
+{-# INLINE runWeightedT #-}
+
+pattern WeightedT :: (Functor m, Semiring s) => m (a, s) -> WeightedT s m a
+pattern WeightedT x <- (runWeightedT -> x) where
+  WeightedT y = WeightedT_ (StateT (\s -> (fmap.fmap) (s<.>) y))
+
+type Weighted s = WeightedT s Identity
+
+pattern Weighted :: Semiring s => (a, s) -> Weighted s a
+pattern Weighted x <- (runWeighted -> x) where
+  Weighted (y,p) = WeightedT_ (StateT (\s -> Identity (y, p<.>s)))
+
+runWeighted
+    :: Semiring s
+    => Weighted s a -> (a, s)
+runWeighted =
+    (coerce :: (WeightedT s Identity a -> Identity (a, s)) -> (WeightedT s Identity a -> (a, s)))
+        runWeightedT
+{-# INLINE runWeighted #-}
+
+instance (Semiring s, Monad m) => MonadWriter (Mul s) (WeightedT s m) where
+  writer (x, Mul s) = WeightedT (pure (x, s))
+  {-# INLINE writer #-}
+  listen (WeightedT_ s) = WeightedT_ ((,) <$> s <*> gets Mul)
+  {-# INLINE listen #-}
+  pass (WeightedT_ s) = WeightedT_ (passS s) where
+    passS = (=<<) (uncurry (<$) . fmap (modify . coerce))
+  {-# INLINE pass #-}
+
+evalWeightedT :: (Monad m, Semiring s) => WeightedT s m a -> m a
+evalWeightedT =
+    (coerce :: (StateT s m a -> m a) -> WeightedT s m a -> m a)
+        (`evalStateT` one)
+{-# INLINE evalWeightedT #-}
+
+execWeightedT :: (Monad m, Semiring s) => WeightedT s m a -> m s
+execWeightedT =
+    (coerce :: (StateT s m a -> m s) -> WeightedT s m a -> m s)
+        (`execStateT` one)
+{-# INLINE execWeightedT #-}
+
+evalWeighted :: Semiring s => Weighted s a -> a
+evalWeighted =
+    (coerce :: (State s a -> a) -> Weighted s a -> a)
+        (`evalState` one)
+{-# INLINE evalWeighted #-}
+
+execWeighted :: Semiring s => Weighted s a -> s
+execWeighted =
+    (coerce :: (State s a -> s) -> Weighted s a -> s)
+        (`execState` one)
+{-# INLINE execWeighted #-}
+
+instance (Alternative m, Monad m, Semiring s) => Alternative (WeightedT s m) where
+  empty = WeightedT empty
+  WeightedT x <|> WeightedT y = WeightedT (x <|> y)
+  _ <|> _ = undefined
+
diff --git a/weighted.cabal b/weighted.cabal
new file mode 100644
--- /dev/null
+++ b/weighted.cabal
@@ -0,0 +1,25 @@
+name:                weighted
+version:             0.1.0.1
+synopsis:            Writer monad which uses semiring constraint
+description:         Writer monad which uses semiring constraint
+homepage:            https://github.com/oisdk/weighted
+license:             MIT
+license-file:        LICENSE
+author:              Donnacha Oisín Kidney
+maintainer:          mail@doisinkidney.com
+copyright:           2016 Donnacha Oisín Kidney
+category:            Control
+build-type:          Simple
+cabal-version:       >=1.10
+
+library
+  hs-source-dirs:      src
+  exposed-modules:     Control.Monad.Weighted
+  build-depends:       base >= 4.9 && < 5
+                     , semiring-num >= 0.5.1.1
+                     , mtl >= 2.2
+  default-language:    Haskell2010
+
+source-repository head
+  type:     git
+  location: https://github.com/oisdk/weighted
