diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -6,6 +6,9 @@
 
 This software currently has *beta* status, i.e. it had seen limited testing.
 
+Version 0.5   - `Poll` has an additional type-parameter representing the socket
+                type. This integrates `poll` with the monadic layer.
+
 Version 0.4   - Return `Async a` in `System.ZMQ3.Monadic.async`. Also require
                 `Data.List.NonEmpty` in `System.ZMQ3.sendMulti`.
 
diff --git a/src/System/ZMQ3.hs b/src/System/ZMQ3.hs
--- a/src/System/ZMQ3.hs
+++ b/src/System/ZMQ3.hs
@@ -80,6 +80,7 @@
   , Sender
   , Receiver
   , Subscriber
+  , SocketLike
 
     -- ** Socket Types
   , Pair(..)
@@ -204,11 +205,12 @@
 import Prelude hiding (init)
 import Control.Applicative
 import Control.Exception
-import Control.Monad (unless, void)
+import Control.Monad (unless)
 import Control.Monad.IO.Class
 import Data.List (intersect, foldl')
 import Data.List.NonEmpty (NonEmpty)
 import Data.Restricted
+import Data.Traversable (forM)
 import Foreign hiding (throwIf, throwIf_, throwIfNull, void)
 import Foreign.C.String
 import Foreign.C.Types (CInt, CShort)
@@ -365,12 +367,13 @@
   | Err    -- ^ ZMQ_POLLERR
   deriving (Eq, Ord, Read, Show)
 
--- | Type representing a descriptor, poll is waiting for
--- (either a 0MQ socket or a file descriptor) plus the type
--- of event to wait for.
-data Poll m where
-    Sock :: Socket s -> [Event] -> Maybe ([Event] -> m ()) -> Poll m
-    File :: Fd -> [Event] -> Maybe ([Event] -> m ()) -> Poll m
+-- | A 'Poll' value contains the object to poll (a 0MQ socket or a file
+-- descriptor), the set of 'Event's which are of interest and--optionally--
+-- a callback-function which is invoked iff the set of interested events
+-- overlaps with the actual events.
+data Poll s m where
+    Sock :: s t -> [Event] -> Maybe ([Event] -> m ()) -> Poll s m
+    File :: Fd -> [Event] -> Maybe ([Event] -> m ()) -> Poll s m
 
 -- | Return the runtime version of the underlying 0MQ library as a
 -- (major, minor, patch) triple.
@@ -780,11 +783,9 @@
         tag <- peek ptr :: IO CInt
         return . Just $ eventMessage str dat (ZMQEventType tag)
 
--- | Polls for events on the given 'Poll' descriptors. Returns the
--- same list of 'Poll' descriptors with an "updated" 'PollEvent' field
--- (cf. zmq_poll). Sockets which have seen no activity have 'None' in
--- their 'PollEvent' field.
-poll :: MonadIO m => Timeout -> [Poll m] -> m [[Event]]
+-- | Polls for events on the given 'Poll' descriptors. Returns a list of
+-- events per descriptor which have occured.
+poll :: (SocketLike s, MonadIO m) => Timeout -> [Poll s m] -> m [[Event]]
 poll _    [] = return []
 poll to desc = do
     let len = length desc
@@ -795,22 +796,20 @@
         peekArray len ptr
     mapM fromZMQPoll (zip desc ps')
   where
-    toZMQPoll :: MonadIO m => Poll m -> ZMQPoll
-    toZMQPoll (Sock (Socket (SocketRepr s _)) e _) =
-        ZMQPoll s 0 (combine (map fromEvent e)) 0
+    toZMQPoll :: (SocketLike s, MonadIO m) => Poll s m -> ZMQPoll
+    toZMQPoll (Sock s e _) =
+        ZMQPoll (_socket . _socketRepr . toSocket $ s) 0 (combine (map fromEvent e)) 0
 
     toZMQPoll (File (Fd s) e _) =
         ZMQPoll nullPtr (fromIntegral s) (combine (map fromEvent e)) 0
 
-    fromZMQPoll :: MonadIO m => (Poll m, ZMQPoll) -> m [Event]
+    fromZMQPoll :: (SocketLike s, MonadIO m) => (Poll s m, ZMQPoll) -> m [Event]
     fromZMQPoll (p, zp) = do
         let e = toEvents . fromIntegral . pRevents $ zp
         let (e', f) = case p of
                         (Sock _ x g) -> (x, g)
                         (File _ x g) -> (x, g)
-        unless (null (e `intersect` e')) $
-            maybe (return ()) ($ e) f
-        return e
+        forM f (unless (null (e `intersect` e')) . ($ e)) >> return e
 
     fromEvent :: Event -> CShort
     fromEvent In   = fromIntegral . pollVal $ pollIn
@@ -862,8 +861,8 @@
 -- messages, received on both frontend and backend, to the capture socket.
 proxy :: Socket a -> Socket b -> Maybe (Socket c) -> IO ()
 proxy front back capture =
-  onSocket "proxy-front" front $ \f ->
-    onSocket "proxy-back" back $ \b ->
-      void (c_zmq_proxy f b c)
+    onSocket "proxy-front" front $ \f ->
+    onSocket "proxy-back"  back  $ \b ->
+        throwIfMinus1Retry_ "c_zmq_proxy" $ c_zmq_proxy f b c
   where
     c = maybe nullPtr (_socket . _socketRepr) capture
diff --git a/src/System/ZMQ3/Base.hsc b/src/System/ZMQ3/Base.hsc
--- a/src/System/ZMQ3/Base.hsc
+++ b/src/System/ZMQ3/Base.hsc
@@ -236,7 +236,7 @@
 
 -- proxy
 
-foreign import ccall unsafe "zmq.h zmq_proxy"
+foreign import ccall safe "zmq.h zmq_proxy"
     c_zmq_proxy :: ZMQSocket -> ZMQSocket -> ZMQSocket -> IO CInt
 
 -- poll
diff --git a/src/System/ZMQ3/Internal.hs b/src/System/ZMQ3/Internal.hs
--- a/src/System/ZMQ3/Internal.hs
+++ b/src/System/ZMQ3/Internal.hs
@@ -1,15 +1,16 @@
 module System.ZMQ3.Internal
-    ( Context(..)
-    , Socket(..)
-    , SocketRepr(..)
-    , SocketType(..)
-    , Message(..)
-    , Flag(..)
+    ( Context    (..)
+    , Socket     (..)
+    , SocketRepr (..)
+    , SocketType (..)
+    , SocketLike (..)
+    , Message    (..)
+    , Flag       (..)
     , Timeout
     , Size
-    , Switch (..)
-    , EventType (..)
-    , EventMsg (..)
+    , Switch     (..)
+    , EventType  (..)
+    , EventMsg   (..)
 
     , messageOf
     , messageOfLazy
@@ -121,6 +122,12 @@
 -- | Socket types.
 class SocketType a where
     zmqSocketType :: a -> ZMQSocketType
+
+class SocketLike s where
+    toSocket :: s t -> Socket t
+
+instance SocketLike Socket where
+    toSocket = id
 
 -- A 0MQ Message representation.
 newtype Message = Message { msgPtr :: ZMQMsgPtr }
diff --git a/src/System/ZMQ3/Monadic.hs b/src/System/ZMQ3/Monadic.hs
--- a/src/System/ZMQ3/Monadic.hs
+++ b/src/System/ZMQ3/Monadic.hs
@@ -28,6 +28,7 @@
   , Z.Sender
   , Z.Receiver
   , Z.Subscriber
+  , Z.SocketLike
 
   -- ** Socket Types
   , Z.Pair(..)
@@ -181,6 +182,9 @@
 -- | The ZMQ socket, parameterised by 'SocketType' and belonging to
 -- a particular 'ZMQ' thread.
 newtype Socket z t = Socket { _unsocket :: Z.Socket t }
+
+instance I.SocketLike (Socket z) where
+    toSocket = _unsocket
 
 instance Monad (ZMQ z) where
     return = ZMQ . return
diff --git a/zeromq3-haskell.cabal b/zeromq3-haskell.cabal
--- a/zeromq3-haskell.cabal
+++ b/zeromq3-haskell.cabal
@@ -1,5 +1,5 @@
 name:               zeromq3-haskell
-version:            0.4
+version:            0.5
 synopsis:           Bindings to ZeroMQ 3.x
 category:           System, FFI
 license:            MIT
