diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,27 +1,31 @@
 This library provides Haskell bindings to 0MQ 3.2.x (http://zeromq.org).
+API documentation can be found at: http://twittner.github.io/zeromq-haskell/
 
 Current status
 --------------
 
 This software currently has *beta* status, i.e. it had seen limited testing.
 
-Version 0.3.0 - Add monadic layer on top of System.ZMQ3 and substitute
+Version 0.4   - Return `Async a` in `System.ZMQ3.Monadic.async`. Also require
+                `Data.List.NonEmpty` in `System.ZMQ3.sendMulti`.
+
+Version 0.3   - Add monadic layer on top of System.ZMQ3 and substitute
                 String for ByteString in a number of cases, where the 0MQ
-                API speaks of "binary data", i.e. subscribe/unsubscribe,
-                identity/setIdentity and setTcpAcceptFilter.
+                API speaks of "binary data", i.e. `subscribe`/`unsubscribe`,
+                `identity`/`setIdentity` and `setTcpAcceptFilter`.
 
 Version 0.2   - Add additional functionality from 3.2 stable release, e.g.
                 zmq_proxy support, new socket options, socket monitoring etc.
-                *API Change*: withContext no longer accepts the number of
+                *API Change*: `withContext` no longer accepts the number of
                 I/O threads as first argument.
 
-Version 0.1.4 - Expose 'waitRead' and 'waitWrite'.
+Version 0.1.4 - Expose `waitRead` and `waitWrite`.
 
-Version 0.1.3 - Deprecated 'Xreq', 'XRep' in favour of 'Dealer' and 'Router'
+Version 0.1.3 - Deprecated `Xreq`, `XRep` in favour of `Dealer` and `Router`
                 as in libzmq. Fixes to compile and run with GHC 7.4.1.
 
-Version 0.1.2 - Add 'sendMulti' and 'receiveMulti'. Rename 'SndMore' to
-                'SendMore'.
+Version 0.1.2 - Add `sendMulti` and `receiveMulti`. Rename `SndMore` to
+                `SendMore`.
 
 Version 0.1.1 - Include better error message when trying to build against
                 invalid 0MQ version.
diff --git a/src/System/ZMQ3.hs b/src/System/ZMQ3.hs
--- a/src/System/ZMQ3.hs
+++ b/src/System/ZMQ3.hs
@@ -202,24 +202,27 @@
 ) where
 
 import Prelude hiding (init)
-import qualified Prelude as P
 import Control.Applicative
 import Control.Exception
 import Control.Monad (unless, void)
 import Control.Monad.IO.Class
 import Data.List (intersect, foldl')
+import Data.List.NonEmpty (NonEmpty)
 import Data.Restricted
 import Foreign hiding (throwIf, throwIf_, throwIfNull, void)
 import Foreign.C.String
 import Foreign.C.Types (CInt, CShort)
-import qualified Data.ByteString as SB
-import qualified Data.ByteString.Lazy as LB
 import System.Posix.Types (Fd(..))
 import System.ZMQ3.Base
-import qualified System.ZMQ3.Base as B
 import System.ZMQ3.Internal
 import System.ZMQ3.Error
 
+import qualified Data.ByteString      as SB
+import qualified Data.ByteString.Lazy as LB
+import qualified Data.List.NonEmpty   as S
+import qualified Prelude              as P
+import qualified System.ZMQ3.Base     as B
+
 import GHC.Conc (threadWaitRead, threadWaitWrite)
 
 -- | Socket to communicate with a single peer. Allows for only a
@@ -712,10 +715,10 @@
 -- This function applies the 'SendMore' 'Flag' between all message parts.
 -- 0MQ guarantees atomic delivery of a multi-part message
 -- (cf. zmq_sendmsg for details).
-sendMulti :: Sender a => Socket a -> [SB.ByteString] -> IO ()
+sendMulti :: Sender a => Socket a -> NonEmpty SB.ByteString -> IO ()
 sendMulti sock msgs = do
-    mapM_ (send sock [SendMore]) (P.init msgs)
-    send sock [] (last msgs)
+    mapM_ (send sock [SendMore]) (S.init msgs)
+    send sock [] (S.last msgs)
 
 -- | Receive a 'ByteString' from socket (cf. zmq_recvmsg).
 --
@@ -782,6 +785,7 @@
 -- (cf. zmq_poll). Sockets which have seen no activity have 'None' in
 -- their 'PollEvent' field.
 poll :: MonadIO m => Timeout -> [Poll m] -> m [[Event]]
+poll _    [] = return []
 poll to desc = do
     let len = length desc
     let ps  = map toZMQPoll desc
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
@@ -145,23 +145,26 @@
 where
 
 import Control.Applicative
-import Control.Concurrent (forkIO)
+import Control.Concurrent.Async (Async)
 import Control.Monad
 import Control.Monad.Trans.Reader
 import Control.Monad.IO.Class
 import Control.Monad.CatchIO
 import Data.Int
 import Data.IORef
+import Data.List.NonEmpty (NonEmpty)
 import Data.Restricted
 import Data.Word
 import Data.ByteString (ByteString)
 import System.Posix.Types (Fd)
-import qualified Data.ByteString.Lazy as Lazy
-import qualified Control.Exception as E
-import qualified System.ZMQ3 as Z
-import qualified System.ZMQ3.Internal as I
-import qualified Control.Monad.CatchIO as M
 
+import qualified Control.Concurrent.Async as A
+import qualified Control.Exception        as E
+import qualified Control.Monad.CatchIO    as M
+import qualified Data.ByteString.Lazy     as Lazy
+import qualified System.ZMQ3              as Z
+import qualified System.ZMQ3.Internal     as I
+
 data ZMQEnv = ZMQEnv
   { _refcount :: !(IORef Word)
   , _context  :: !Z.Context
@@ -209,7 +212,7 @@
     make = ZMQEnv <$> newIORef 1 <*> Z.context <*> newIORef []
 
 -- | Run the given 'ZMQ' computation asynchronously, i.e. this function
--- runs the computation in a new thread using 'forkIO'.
+-- runs the computation in a new thread using 'Control.Concurrent.Async.async'.
 -- /N.B./ reference counting is used to prolong the lifetime of the
 -- 'System.ZMQ.Context' encapsulated in 'ZMQ' as necessary, e.g.:
 --
@@ -224,12 +227,11 @@
 -- Here, 'runZMQ' will finish before the code section in 'async', but due to
 -- reference counting, the 'System.ZMQ3.Context' will only be disposed after
 -- 'async' finishes as well.
-async :: ZMQ z a -> ZMQ z ()
+async :: ZMQ z a -> ZMQ z (Async a)
 async z = ZMQ $ do
     e <- ask
     liftIO $ atomicModifyIORef (_refcount e) $ \n -> (succ n, ())
-    _ <- liftIO . forkIO $ (runReaderT (_unzmq z) e >> return ()) `E.finally` destroy e
-    return ()
+    liftIO . A.async $ (runReaderT (_unzmq z) e) `E.finally` destroy e
 
 ioThreads :: ZMQ z Word
 ioThreads = onContext Z.ioThreads
@@ -274,7 +276,7 @@
 send' :: Z.Sender t => Socket z t -> [Z.Flag] -> Lazy.ByteString -> ZMQ z ()
 send' s f = liftIO . Z.send' (_unsocket s) f
 
-sendMulti :: Z.Sender t => Socket z t -> [ByteString] -> ZMQ z ()
+sendMulti :: Z.Sender t => Socket z t -> NonEmpty ByteString -> ZMQ z ()
 sendMulti s = liftIO . Z.sendMulti (_unsocket s)
 
 receive :: Z.Receiver t => Socket z t -> ZMQ z ByteString
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.3.1
+version:            0.4
 synopsis:           Bindings to ZeroMQ 3.x
 category:           System, FFI
 license:            MIT
@@ -41,8 +41,10 @@
     extensions:           CPP
                         , ForeignFunctionInterface
     build-depends:        base >= 3 && < 5
+                        , async
                         , containers
                         , bytestring
+                        , semigroups
                         , transformers
                         , MonadCatchIO-transformers
     if os(freebsd)
