diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -4,6 +4,8 @@
 
 Haskell type-safe bindings for working with i3 using it's unix socket IPC
 
+## Subscribing
+
 Subscribe to events:
 
 ```haskell
@@ -15,6 +17,26 @@
 main = subscribe print [Sub.Workspace, Sub.Window]
 ```
 
+An example of explicitly matching on some events and printing their fields:
+
+```haskell
+import qualified I3IPC.Subscribe               as Sub
+import           I3IPC.Event
+import           I3IPC                          ( subscribe )
+
+main :: IO ()
+main = subscribe handle [Sub.Workspace, Sub.Window]
+ where
+  handle :: Either String Event -> IO ()
+  handle (Right evt) = case evt of
+    Workspace WorkspaceEvent { wrk_current } -> print wrk_current
+    Window WindowEvent { win_container } -> print win_container
+    _ -> error "No other event types"
+  handle (Left err) = error err
+```
+
+## Sending Messages
+
 Sending Messages to i3:
 
 ```haskell
@@ -25,7 +47,7 @@
 main :: IO ()
 main = do
     soc <- connecti3
-    print getWorkspaces
+    print $ getWorkspaces soc
 ```
 
 Alternatively, you can ignore the convenience functions and construct these messages yourself:
@@ -41,5 +63,7 @@
     soc <- connecti3
     print $ Msg.sendMsg soc Msg.Workspaces >> receiveMsg soc
 ```
+
+## Community
 
 I'm happy to take PRs or suggestions, or simply fix issues for this library.
diff --git a/i3ipc.cabal b/i3ipc.cabal
--- a/i3ipc.cabal
+++ b/i3ipc.cabal
@@ -1,5 +1,5 @@
 name:                i3ipc
-version:             0.1.0.0
+version:             0.1.0.1
 description:         Library for controlling i3 through it's IPC. i3 communicates using a JSON interface over a unix socket.
                      For JSON parsing I'm using Aeson. I've written out all the records and types to allow anyone to 
                      easily interact with i3 from a Haskell application.
diff --git a/src/I3IPC.hs b/src/I3IPC.hs
--- a/src/I3IPC.hs
+++ b/src/I3IPC.hs
@@ -21,6 +21,7 @@
       getSocketPath
     , Response(..)
     , subscribe
+    , subscribeM
     , receive
     , receive'
     , receiveMsg
@@ -60,6 +61,7 @@
 import qualified I3IPC.Event                        as Evt
 import           I3IPC.Reply
 
+import           Control.Monad.IO.Class
 import           System.Environment                  ( lookupEnv )
 import           Data.Maybe                          ( isJust )
 import           Data.Semigroup                      ( (<>) )
@@ -100,29 +102,38 @@
 -- | Subscribe with a list of 'I3IPC.Subscribe.Subscribe' types, and subscribe will to respond with specific 'I3IPC.Event.Event'
 subscribe :: (Either String Evt.Event -> IO ()) -> [Sub.Subscribe] -> IO ()
 subscribe handle subtypes = do
-    soc  <- socket AF_UNIX Stream 0
-    addr <- getSocketPath
-    case addr of
-        Nothing -> putStrLn "Failed to get i3 socket path" >> exitFailure
-        Just addr' ->
-            connect soc (SockAddrUnix $ BL.unpack addr')
-                >> Msg.sendMsgPayload soc Msg.Subscribe (encode subtypes)
-                >> receiveMsg soc
-                >> handleSoc soc
-                >> close soc
+    soc <- connecti3
+    Msg.sendMsgPayload soc Msg.Subscribe (encode subtypes)
+        >> receiveMsg soc
+        >> handleSoc soc
+        >> close soc
   where
     handleSoc soc = do
         r <- receiveEvent soc
         handle r
         handleSoc soc
 
+-- | A version of 'subscribe' that allows the use of any monad transformer on top of MonadIO
+subscribeM
+    :: MonadIO m => (Either String Evt.Event -> m ()) -> [Sub.Subscribe] -> m ()
+subscribeM handle subtypes = do
+    soc <- liftIO connecti3
+    liftIO
+        $  Msg.sendMsgPayload soc Msg.Subscribe (encode subtypes)
+        >> receiveMsg soc
+        >> pure ()
+    handleSoc soc >> liftIO (close soc)
+  where
+    handleSoc soc = do
+        r <- liftIO $ receiveEvent soc
+        handle r
+        handleSoc soc
 
 -- | Connect to an i3 socket and return it
 connecti3 :: IO Socket
 connecti3 = do
-    soc  <- socket AF_UNIX Stream 0
-    addr <- getSocketPath
-    case addr of
+    soc <- socket AF_UNIX Stream 0
+    getSocketPath >>= \case
         Nothing    -> putStrLn "Failed to get i3 socket path" >> exitFailure
         Just addr' -> do
             connect soc (SockAddrUnix $ BL.unpack addr')
@@ -291,11 +302,19 @@
 --
 -- Commonly, you just want to subscribe to a set of event types and do something with the response:
 --
--- > import qualified I3IPC.Subscribe   as Sub
--- > import           I3IPC              ( subscribe )
+-- > import qualified I3IPC.Subscribe               as Sub
+-- > import           I3IPC.Event
+-- > import           I3IPC                          ( subscribe )
 -- > 
 -- > main :: IO ()
--- > main = subscribe print [Sub.Workspace, Sub.Window]
+-- > main = subscribe handle [Sub.Workspace, Sub.Window]
+-- >  where
+-- >   handle :: Either String Event -> IO ()
+-- >   handle (Right evt) = case evt of
+-- >     Workspace WorkspaceEvent { wrk_current } -> print wrk_current
+-- >     Window WindowEvent { win_container } -> print win_container
+-- >     _ -> error "No other event types"
+-- >   handle (Left err) = error err
 --
 
 -- $msg
