diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2012, Henning Thielemann
+
+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.
+
+    * The names of contributors may not 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.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,3 @@
+#! /usr/bin/env runhaskell
+> import Distribution.Simple
+> main = defaultMain
diff --git a/src/Control/Concurrent/STM/Split/Chan.hs b/src/Control/Concurrent/STM/Split/Chan.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/Split/Chan.hs
@@ -0,0 +1,49 @@
+module Control.Concurrent.STM.Split.Chan (
+   T,
+   In,
+   Out,
+   newIO,
+   new,
+   read,
+   write,
+   writeIO,
+   ) where
+
+import qualified Control.Concurrent.STM.Split.Class as Split
+
+import qualified Control.Concurrent.STM.TChan as Chan
+import Control.Monad.STM (STM, atomically, )
+
+import Prelude (IO, return, ($), )
+
+
+newtype T dir a = Cons (Chan.TChan a)
+
+type In  = T Split.In
+type Out = T Split.Out
+
+
+instance Split.C T where
+   newIO = newIO
+   new = new
+   read = read
+   write = write
+
+newIO :: IO (In a, Out a)
+newIO = do
+   v <- Chan.newTChanIO
+   return (Cons v, Cons v)
+
+new :: STM (In a, Out a)
+new = do
+   v <- Chan.newTChan
+   return (Cons v, Cons v)
+
+read :: Out a -> STM a
+read (Cons v) = Chan.readTChan v
+
+write :: In a -> a -> STM ()
+write (Cons v) a = Chan.writeTChan v a
+
+writeIO :: In a -> a -> IO ()
+writeIO chan a = atomically $ write chan a
diff --git a/src/Control/Concurrent/STM/Split/Class.hs b/src/Control/Concurrent/STM/Split/Class.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/Split/Class.hs
@@ -0,0 +1,23 @@
+module Control.Concurrent.STM.Split.Class (
+   In, Out, C, newIO, new, read, write,
+   ) where
+
+import Control.Monad.STM (STM, )
+
+import Prelude (IO, )
+
+
+data In = In
+data Out = Out
+
+_dummyIn :: In
+_dummyIn = In
+
+_dummyOut :: Out
+_dummyOut = Out
+
+class C chan where
+   newIO :: IO (chan In a, chan Out a)
+   new :: STM (chan In a, chan Out a)
+   read :: chan Out a -> STM a
+   write :: chan In a -> a -> STM ()
diff --git a/src/Control/Concurrent/STM/Split/MVar.hs b/src/Control/Concurrent/STM/Split/MVar.hs
new file mode 100644
--- /dev/null
+++ b/src/Control/Concurrent/STM/Split/MVar.hs
@@ -0,0 +1,72 @@
+module Control.Concurrent.STM.Split.MVar (
+   T,
+   In,
+   Out,
+   newEmptyIO,
+   newEmpty,
+   newIO,
+   new,
+   take,
+   put,
+{-
+   write,
+   clear,
+-}
+   ) where
+
+import qualified Control.Concurrent.STM.Split.Class as Split
+
+import qualified Control.Concurrent.STM.TMVar as MVar
+import Control.Monad.STM (STM, )
+
+import Prelude (IO, return, )
+
+
+newtype T dir a = Cons (MVar.TMVar a)
+
+type In  = T Split.In
+type Out = T Split.Out
+
+
+instance Split.C T where
+   newIO = newEmptyIO
+   new = newEmpty
+   read = take
+   write = put
+
+newEmptyIO :: IO (In a, Out a)
+newEmptyIO = do
+   v <- MVar.newEmptyTMVarIO
+   return (Cons v, Cons v)
+
+newEmpty :: STM (In a, Out a)
+newEmpty = do
+   v <- MVar.newEmptyTMVar
+   return (Cons v, Cons v)
+
+newIO :: a -> IO (In a, Out a)
+newIO a = do
+   v <- MVar.newTMVarIO a
+   return (Cons v, Cons v)
+
+new :: a -> STM (In a, Out a)
+new a = do
+   v <- MVar.newTMVar a
+   return (Cons v, Cons v)
+
+take :: Out a -> STM a
+take (Cons v) = MVar.takeTMVar v
+
+put :: In a -> a -> STM ()
+put (Cons v) a = MVar.putTMVar v a
+
+
+{-
+write :: In a -> a -> STM ()
+write var a =
+   clear var >> put var a
+
+clear :: In a -> STM ()
+clear (Cons v) =
+   MVar.tryTakeTMVar v >> return ()
+-}
diff --git a/stm-split.cabal b/stm-split.cabal
new file mode 100644
--- /dev/null
+++ b/stm-split.cabal
@@ -0,0 +1,48 @@
+Name:             stm-split
+Version:          0.0
+License:          BSD3
+License-File:     LICENSE
+Author:           Henning Thielemann <haskell@henning-thielemann.de>
+Maintainer:       Henning Thielemann <haskell@henning-thielemann.de>
+Category:         Concurrent
+Build-Type:       Simple
+Synopsis:         TMVars, TVars and TChans with distinguished input and output side
+Description:
+  Transactional MVars, Vars and Channels with distinguished input and output side.
+  When threads communicate via a TMVar, a TVar or a TChan
+  there are often clearly defined roles,
+  which thread is the sender and which one is receiver.
+  We provide wrappers around the standard concurrency communication channels
+  that make the distinction clear and type safe.
+  .
+  For example, if a function has a parameter of type @TChan.In@
+  then it is sure that it will only write to that channel.
+  Additionally if the compiler warns about an unused @TChan.Out@
+  that was created by @TChan.new@
+  then you know that the receiver part of your communication is missing.
+  .
+  See also package @concurrent-split@ for non-transactional communication.
+  This package follows the same idea as @chan-split@ but is strictly Haskell 98.
+Tested-With:      GHC==6.12.3, GHC==7.4.1
+Cabal-Version:    >=1.6
+Build-Type:       Simple
+Source-Repository this
+  Tag:         0.0
+  Type:        darcs
+  Location:    http://code.haskell.org/~thielema/stm-split/
+
+Source-Repository head
+  Type:        darcs
+  Location:    http://code.haskell.org/~thielema/stm-split/
+
+Library
+  Build-Depends:
+    stm >=2.2 && <2.4,
+    base >=4 && <5
+
+  GHC-Options:      -Wall
+  Hs-Source-Dirs:   src
+  Exposed-Modules:
+    Control.Concurrent.STM.Split.Class
+    Control.Concurrent.STM.Split.MVar
+    Control.Concurrent.STM.Split.Chan
