diff --git a/machines-io.cabal b/machines-io.cabal
--- a/machines-io.cabal
+++ b/machines-io.cabal
@@ -1,5 +1,5 @@
 name:                machines-io
-version:             0.0.0.1
+version:             0.1.0.0
 synopsis:            IO utilities for the machines library
 homepage:            http://github.com/aloiscochard/machines-io
 license:             Apache-2.0
@@ -17,7 +17,8 @@
   exposed-modules: 
     System.IO.Machine
   build-depends:       
-    base >=4.7 && <4.8
-    , chunked-data
-    , machines
-    , transformers
+    base >=4.6 && < 5
+    , bytestring          >= 0.10     && < 0.11
+    , chunked-data        >= 0.1      && < 0.2
+    , machines            >= 0.2      && < 0.3
+    , transformers        >= 0.3      && < 0.5
diff --git a/src/System/IO/Machine.hs b/src/System/IO/Machine.hs
--- a/src/System/IO/Machine.hs
+++ b/src/System/IO/Machine.hs
@@ -1,40 +1,67 @@
-{-# LANGUAGE DoAndIfThenElse #-}
 {-# LANGUAGE Rank2Types #-}
-{-# LANGUAGE KindSignatures #-}
 module System.IO.Machine where
 
+import Control.Applicative ((<$>))
 import Control.Monad (when)
 import Control.Monad.IO.Class (MonadIO, liftIO)
 import Data.IOData (IOData, hGetLine, hPutStrLn)
 import Data.Machine
+import Data.Word (Word8)
 import System.IO (Handle, IOMode(ReadMode), hClose, hIsEOF, openBinaryFile)
 
-data IODataMode a = IODataMode (Handle -> IO a) (Handle -> a -> IO ())
+import qualified Data.ByteString as BS
+import qualified Data.ByteString.Char8 as BSC8
 
+type DataModeIO m a = MonadIO m => ((Handle -> m a), (Handle -> a -> m ()))
+type SinkIO m k = MonadIO m => forall a. ProcessT m k a
+type SourceIO m a = MonadIO m => forall k. MachineT m k a
+
+type IODataMode a = ((Handle -> IO a), (Handle -> a -> IO ()))
 type IOSink k = forall a. ProcessT IO k a
 type IOSource a = forall k. MachineT IO k a
 
-byLine :: IOData a => IODataMode a
-byLine = IODataMode hGetLine hPutStrLn
+byChar :: IODataMode Char
+byChar = (\h -> BSC8.head <$> BSC8.hGet h 1, \h w -> BSC8.hPut h $ BSC8.pack [w])
 
-sourceIO :: MonadIO m => m r -> (r -> m Bool) -> (r -> m a) -> forall k. MachineT m k a
-sourceIO acquire release read = MachineT $ do
+byWord8 :: IODataMode Word8
+byWord8 = (\h -> BS.head <$> BS.hGet h 1, \h w -> BS.hPut h $ BS.pack [w])
+
+byLine :: IOData a => DataModeIO m a
+byLine = (hGetLine, hPutStrLn)
+
+sourceIO :: IO a -> SourceIO m a
+sourceIO f = repeatedly $ liftIO f >>= yield
+
+sourceHandle :: DataModeIO m a -> Handle -> SourceIO m a
+sourceHandle (r, _) = sourceHandleWith r
+
+sourceIOWith :: m r -> (r -> m Bool) -> (r -> m a) -> SourceIO m a
+sourceIOWith acquire release read = MachineT $ do
   r         <- acquire
   released  <- release r
   if released then
     return Stop
   else do
     x <- read r
-    return . Yield x $ sourceIO acquire release read
+    return . Yield x $ sourceIOWith acquire release read
 
-sourceHandle :: IODataMode a -> Handle -> IOSource a
-sourceHandle (IODataMode r _) = sourceHandleWith r
+sourceHandleWith :: (Handle -> m a) -> Handle -> SourceIO m a
+sourceHandleWith f h = sourceIOWith (return h) (liftIO . hIsEOF) f
 
-sinkHandle :: IOData a => IODataMode a -> Handle -> IOSink a
-sinkHandle (IODataMode _ w) h = repeatedly $ await >>= \x -> liftIO $ w h x
+sinkIO :: (a -> IO ()) -> SinkIO m a
+sinkIO f = repeatedly $ await >>= liftIO . f
 
-sourceHandleWith :: (Handle -> IO a) -> Handle -> IOSource a
-sourceHandleWith f h = sourceIO (return h) hIsEOF f
+sinkHandle :: IOData a => IODataMode a -> Handle -> SinkIO m a
+sinkHandle (_, w) h = repeatedly $ await >>= liftIO . w h
 
-sinkHandleWith :: IOData a => (Handle -> a -> IO ()) -> Handle -> IOSink a
-sinkHandleWith f h = repeatedly $ await >>= \x -> liftIO $ f h x
+sinkHandleWith :: IOData a => (Handle -> a -> IO ()) -> Handle -> SinkIO m a
+sinkHandleWith f h = repeatedly $ await >>= liftIO . f h
+
+filteredIO :: (a -> IO Bool) -> ProcessT IO a a
+filteredIO p = repeatedly $ do
+  i <- await
+  x <- liftIO $ p i
+  if x then yield i else return ()
+
+printer :: Show a => SinkIO m a
+printer = sinkIO $ liftIO . print
