diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,6 +1,8 @@
 # Changelog for streamly-bytestring
 
-## Unreleased
+## 0.1.1
+
+* Add `fromChunksIO` function to `Streamly.External.ByteString.Lazy` module.
 
 ## 0.1.0.1
 
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,35 +1,19 @@
-# `streamly-bytestring`
+# streamly-bytestring
 
 Library for streamly and bytestring interoperation.
 
-## Description
-
-This package provides `Streamly.External.ByteString` and
-`Streamly.External.ByteString.Lazy`.
-
-### Strict ByteString
-
-`Streamly.External.ByteString` provides functions to for
-interoperation between streamly and strict bytestring.
-
-`fromArray` and `toArray` are used to efficiently convert between
-streamly's pinned array type (`Streamly.Memory.Array`) and bytestring.
-
-`read`, `writeN` and `write` are `Unfold`s & `Fold`s provided by streamly
-that are used to create and consume a stream of `Word8`. `writeN` is more
-efficient than `write` and should be preferred over `write` when possible.
-
-### Lazy Bytestring
+If you are writing code from scratch, please use `Streamly.Memory.Array` which
+is a generalization of `ByteString` and better integrated with streamly.
 
-`Streamly.External.ByteString.Lazy` provides functions to for
-interoperation between streamly and lazy bytestring.
+This library is to enable interoperation of streamly with existing code that
+uses `ByteString`.
 
-`readChunks` and `read` are `Unfold`s. `unfold` from `Streamly.Prelude` can be
-used to create a stream of `Array Word8` or a stream of `Word8` from a
-lazy `ByteString`.
+The package provides APIs to interconvert between strict `Bytestring` and
+streamly `Array Word8` and between lazy `Bytestring` and stream of `Array Word8`.
 
-`toChunks` is defined as `unfold readChunks`. `fromChunks` can be used to create a
-lazy `ByteString` from a stream of `Array Word8` chunks.
+The interconversion in the case of strict `Bytestring` and streamly `Array
+Word8` has no overhead as the underlying representation of ByteString and Array
+are the same, we just need to rewrap the data in a different type.
 
 ## Usage
 
@@ -52,22 +36,12 @@
 
 lazyByteStringSize :: BSL.ByteString -> IO Int
 lazyByteStringSize bsl = S.foldl' (+) 0
-		       $ S.mapM strictByteStringSize
-		       $ S.map Strict.fromArray
-		       $ Lazy.toChunks bsl
+                         $ S.mapM strictByteStringSize
+                         $ S.map Strict.fromArray
+                         $ Lazy.toChunks bsl
 
 fileSize :: FilePath -> IO Int
 fileSize path = do
     bsl <- BSL.readFile path
     lazyByteStringSize bsl
 ```
-
-
-
-
-
-
-
-
-
-
diff --git a/benchmark/Main.hs b/benchmark/Main.hs
--- a/benchmark/Main.hs
+++ b/benchmark/Main.hs
@@ -21,24 +21,30 @@
 
 {-# INLINE benchIO #-}
 benchIO :: NFData b => String -> (Int -> IO a) -> (a -> b) -> Benchmark
-benchIO name src f = bench name $ nfIO $
-    randomRIO (1,1) >>= src >>= return . f
+benchIO name src f = bench name $ nfIO $ randomRIO (1, 1) >>= src >>= return . f
 
 {-# INLINE benchIO' #-}
 benchIO' :: NFData b => String -> (Int -> IO a) -> (a -> IO b) -> Benchmark
-benchIO' name src f = bench name $ nfIO $
-    randomRIO (1,1) >>= src >>= f
+benchIO' name src f = bench name $ nfIO $ randomRIO (1, 1) >>= src >>= f
 
 {-# INLINE fromChunks #-}
 fromChunks :: Monad m => Int -> m BSL.ByteString
 fromChunks n =
-    Lazy.fromChunks
-  $ S.map Strict.toArray
-  $ S.map BS.singleton
-  $ S.map fromIntegral
-  $ S.map (\x -> x `mod` 256)
-  $ S.enumerateFromTo n (n + numChunks)
+    Lazy.fromChunks $
+    S.map Strict.toArray $
+    S.map BS.singleton $
+    S.map fromIntegral $
+    S.map (\x -> x `mod` 256) $ S.enumerateFromTo n (n + numChunks)
 
+{-# INLINE fromChunksIO #-}
+fromChunksIO :: Int -> IO BSL.ByteString
+fromChunksIO n =
+    Lazy.fromChunksIO $
+    S.map Strict.toArray $
+    S.map BS.singleton $
+    S.map fromIntegral $
+    S.map (\x -> x `mod` 256) $ S.enumerateFromTo n (n + numChunks)
+
 {-# INLINE toChunks #-}
 toChunks :: Monad m => BSL.ByteString -> m ()
 toChunks = S.drain . Lazy.toChunks
@@ -46,18 +52,16 @@
 {-# INLINE strictWrite #-}
 strictWrite :: MonadIO m => Int -> m BS.ByteString
 strictWrite n =
-    S.fold Strict.write
-  $ S.map fromIntegral
-  $ S.map (\x -> x `mod` 256)
-  $ S.enumerateFromTo n (n + numElements)
+    S.fold Strict.write $
+    S.map fromIntegral $
+    S.map (\x -> x `mod` 256) $ S.enumerateFromTo n (n + numElements)
 
 {-# INLINE strictWriteN #-}
 strictWriteN :: MonadIO m => Int -> m BS.ByteString
 strictWriteN n =
-    S.fold (Strict.writeN numElements)
-  $ S.map fromIntegral
-  $ S.map (\x -> x `mod` 256)
-  $ S.enumerateFromTo n (n + numElements)
+    S.fold (Strict.writeN numElements) $
+    S.map fromIntegral $
+    S.map (\x -> x `mod` 256) $ S.enumerateFromTo n (n + numElements)
 
 {-# INLINE strictRead #-}
 strictRead :: MonadIO m => BS.ByteString -> m ()
@@ -68,11 +72,13 @@
 lazyRead = S.drain . S.unfold Lazy.read
 
 main :: IO ()
-main = defaultMain
+main =
+    defaultMain
         [ benchIO "Strict Write" strictWrite id
         , benchIO "Strict WriteN" strictWriteN id
         , benchIO' "Strict Read" strictWrite strictRead
         , benchIO' "Lazy Read" fromChunks lazyRead
         , benchIO "fromChunks" fromChunks id
+        , benchIO "fromChunksIO" fromChunksIO id
         , benchIO' "toChunks" fromChunks toChunks
         ]
diff --git a/src/Streamly/External/ByteString.hs b/src/Streamly/External/ByteString.hs
--- a/src/Streamly/External/ByteString.hs
+++ b/src/Streamly/External/ByteString.hs
@@ -36,7 +36,7 @@
 {-# INLINE toArray #-}
 toArray :: ByteString -> Array Word8
 toArray (PS fp off len) = Array nfp endPtr endPtr
-    where
+  where
     nfp = fp `plusForeignPtr` off
     endPtr = unsafeForeignPtrToPtr fp `plusPtr` len
 
@@ -48,9 +48,9 @@
 fromArray Array {..}
     | aLen == 0 = mempty
     | otherwise = PS aStart 0 aLen
-        where
-        aStartPtr = unsafeForeignPtrToPtr aStart
-        aLen = aEnd `minusPtr` aStartPtr
+  where
+    aStartPtr = unsafeForeignPtrToPtr aStart
+    aLen = aEnd `minusPtr` aStartPtr
 
 -- | Unfold a strict ByteString to a stream of Word8.
 {-# INLINE read #-}
diff --git a/src/Streamly/External/ByteString/Lazy.hs b/src/Streamly/External/ByteString/Lazy.hs
--- a/src/Streamly/External/ByteString/Lazy.hs
+++ b/src/Streamly/External/ByteString/Lazy.hs
@@ -1,9 +1,12 @@
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+
 module Streamly.External.ByteString.Lazy
   ( readChunks
   , read
-  
+
   , toChunks
   , fromChunks
+  , fromChunksIO
   )
 where
 
@@ -17,8 +20,10 @@
 import qualified Streamly.External.ByteString as Strict
 import qualified Streamly.Internal.Memory.Array as A
 
+import System.IO.Unsafe (unsafeInterleaveIO)
+
 import Streamly
-import qualified Streamly.Prelude as S
+import qualified Streamly.Internal.Prelude as S
 
 import qualified Data.ByteString.Lazy.Internal as BSLI
 
@@ -28,7 +33,7 @@
 {-# INLINE  readChunks #-}
 readChunks :: Monad m => Unfold m ByteString (Array Word8)
 readChunks = Unfold step seed
-    where
+  where
     seed = return
     step (Chunk bs bl) = return $ Yield (Strict.toArray bs) bl
     step Empty = return $ Stop
@@ -43,7 +48,58 @@
 toChunks :: Monad m => ByteString -> SerialT m (Array Word8)
 toChunks = S.unfold readChunks
 
+{-
+newtype LazyIO a = LazyIO { runLazy :: IO a } deriving (Functor, Applicative)
+
+liftToLazy :: IO a -> LazyIO a
+liftToLazy = LazyIO
+
+instance Monad LazyIO where
+    return = pure
+    LazyIO a >>= f = LazyIO (unsafeInterleaveIO a >>= unsafeInterleaveIO . runLazy . f)
+-}
+
 -- | Convert a serial stream of 'Array' 'Word8' to a lazy 'ByteString'.
+--
+-- IMPORTANT NOTE: This function is lazy only for lazy monads
+-- (e.g. Identity). For strict monads (e.g. /IO/) it consumes the entire input
+-- before generating the output. For /IO/ monad please use fromChunksIO
+-- instead.
+--
+-- For strict monads like /IO/ you could create a newtype wrapper to make the
+-- monad bind operation lazy and lift the stream to that type using hoist, then
+-- you can use this function to generate the bytestring lazily. For example you
+-- can wrap the /IO/ type to make the bind lazy like this:
+--
+-- @
+-- newtype LazyIO a = LazyIO { runLazy :: IO a } deriving (Functor, Applicative)
+--
+-- liftToLazy :: IO a -> LazyIO a
+-- liftToLazy = LazyIO
+--
+-- instance Monad LazyIO where
+--   return = pure
+--   LazyIO a >>= f = LazyIO (unsafeInterleaveIO a >>= unsafeInterleaveIO . runLazy . f)
+-- @
+--
+-- /fromChunks/ can then be used as,
+-- @
+-- {-# INLINE fromChunksIO #-}
+-- fromChunksIO :: SerialT IO (Array Word8) -> IO ByteString
+-- fromChunksIO str = runLazy (fromChunks (S.hoist liftToLazy str))
+-- @
 {-# INLINE fromChunks #-}
 fromChunks :: Monad m => SerialT m (Array Word8) -> m ByteString
 fromChunks = S.foldr BSLI.chunk Empty . S.map Strict.fromArray
+
+-- | Convert a serial stream of 'Array' 'Word8' to a lazy 'ByteString' in the
+-- /IO/ monad.
+{-# INLINE fromChunksIO #-}
+fromChunksIO :: SerialT IO (Array Word8) -> IO ByteString
+fromChunksIO =
+-- Although the /IO/ monad is strict in nature we emulate laziness using
+-- 'unsafeInterleaveIO'.
+    S.foldrM
+        (\x b -> unsafeInterleaveIO b >>= pure . BSLI.chunk x)
+        (pure BSLI.Empty) .
+    S.map Strict.fromArray
diff --git a/streamly-bytestring.cabal b/streamly-bytestring.cabal
--- a/streamly-bytestring.cabal
+++ b/streamly-bytestring.cabal
@@ -1,13 +1,13 @@
 cabal-version: 1.12
 
--- This file has been generated from package.yaml by hpack version 0.33.0.
+-- This file has been generated from package.yaml by hpack version 0.31.2.
 --
 -- see: https://github.com/sol/hpack
 --
--- hash: 025212f67560e558928440828becf41e3f1e28c9e66cb82ac3e415918168f8e3
+-- hash: af662f24c97fa6b630e84ef660885ad0de001dc9face27ef4698f5361e4e5484
 
 name:           streamly-bytestring
-version:        0.1.0.1
+version:        0.1.1
 synopsis:       Library for streamly and bytestring interoperation.
 description:    Please see the README on GitHub at <https://github.com/psibi/streamly-bytestring#readme>
 category:       Streamly, Stream, ByteString
diff --git a/test/Main.hs b/test/Main.hs
--- a/test/Main.hs
+++ b/test/Main.hs
@@ -21,84 +21,112 @@
 import qualified Streamly.External.ByteString.Lazy as Lazy
 import qualified Streamly.Prelude as S
 
-streamToByteString :: MonadAsync m => SerialT m (Array Word8)-> m ByteString
+streamToByteString :: MonadAsync m => SerialT m (Array Word8) -> m ByteString
 streamToByteString stream = S.foldl' (<>) mempty $ S.map Strict.fromArray stream
 
 checkFileContent :: FilePath -> Handle -> IO ()
 checkFileContent filename handle' = do
-  print $ "Checking " <> filename
-  bsContent <- BS.hGetContents handle'
-  handle <- openFile filename ReadMode
-  bsStreamly <- streamToByteString $ S.unfold readChunks handle
-  bsContent `shouldBe` bsStreamly
+    print $ "Checking " <> filename
+    bsContent <- BS.hGetContents handle'
+    handle <- openFile filename ReadMode
+    bsStreamly <- streamToByteString $ S.unfold readChunks handle
+    bsContent `shouldBe` bsStreamly
 
 word8List :: Int -> IO [Word8]
-word8List l = S.toList
-       $ S.take l
-       $ S.map fromIntegral
-       $ S.map (\x -> abs x `mod` 256)
-       $ S.repeatM (randomIO :: IO Int)
+word8List l =
+    S.toList $
+    S.take l $
+    S.map fromIntegral $
+    S.map (\x -> abs x `mod` 256) $ S.repeatM (randomIO :: IO Int)
 
 propFoldTestStrict :: [Word8] -> Spec
 propFoldTestStrict bl =
-  prop ("Strict: fold write . fromList = pack" ++ " -- Size: " ++ show (length bl) ++ " bytes") $ do
-  bl' <- fmap BS.unpack $ S.fold Strict.write $ S.fromList bl
-  bl' `shouldBe` bl
+    prop
+        ("Strict: fold write . fromList = pack" ++
+         " -- Size: " ++ show (length bl) ++ " bytes") $ do
+        bl' <- fmap BS.unpack $ S.fold Strict.write $ S.fromList bl
+        bl' `shouldBe` bl
 
 propNFoldTestStrict :: Int -> [Word8] -> Spec
 propNFoldTestStrict n bl =
-  prop ("Strict: fold (writeN n) . fromList = pack . take n" ++ " -- Size: " ++ show n ++ " bytes") $ do
-  bl' <- fmap BS.unpack $ S.fold (Strict.writeN n) $ S.fromList bl
-  bl' `shouldBe` take n bl
+    prop
+        ("Strict: fold (writeN n) . fromList = pack . take n" ++
+         " -- Size: " ++ show n ++ " bytes") $ do
+        bl' <- fmap BS.unpack $ S.fold (Strict.writeN n) $ S.fromList bl
+        bl' `shouldBe` take n bl
 
 propUnfoldTestStrict :: [Word8] -> Spec
 propUnfoldTestStrict bl =
-  prop ("Strict: toList . unfold read . pack = id" ++ " -- Size: " ++ show (length bl) ++ " bytes") $ do
-  bl' <- S.toList (S.unfold Strict.read (BS.pack bl))
-  bl' `shouldBe` bl
+    prop
+        ("Strict: toList . unfold read . pack = id" ++
+         " -- Size: " ++ show (length bl) ++ " bytes") $ do
+        bl' <- S.toList (S.unfold Strict.read (BS.pack bl))
+        bl' `shouldBe` bl
 
 propUnfoldTestLazy :: [Word8] -> Spec
 propUnfoldTestLazy bl =
-  prop ("Lazy: toList . unfold read . pack = id" ++ " -- Size: " ++ show (length bl) ++ " bytes") $ do
-  bl' <- S.toList (S.unfold Lazy.read (BSL.pack bl))
-  bl' `shouldBe` bl
+    prop
+        ("Lazy: toList . unfold read . pack = id" ++
+         " -- Size: " ++ show (length bl) ++ " bytes") $ do
+        bl' <- S.toList (S.unfold Lazy.read (BSL.pack bl))
+        bl' `shouldBe` bl
 
-testFromChunksLaziness :: Word8 -> IO Word8
-testFromChunksLaziness h = do
-  lbs <- Lazy.fromChunks $ S.fromList [Strict.toArray (BS.singleton h), undefined]
-  return $ BSL.head lbs
+propFromChunks :: Spec
+propFromChunks =
+    prop ("Lazy.fromChunks = BSL.fromChunks") $ \aL -> do
+        x1 <- Lazy.fromChunks $ S.map Strict.toArray $ S.fromList aL
+        let x2 = BSL.fromChunks aL
+        x1 `shouldBe` x2
 
+propFromChunksIO :: Spec
+propFromChunksIO =
+    prop ("Lazy.fromChunks = BSL.fromChunks") $ \aL -> do
+        x1 <- Lazy.fromChunksIO $ S.map Strict.toArray $ S.fromList aL
+        let x2 = BSL.fromChunks aL
+        x1 `shouldBe` x2
+
+testFromChunksIOLaziness :: Word8 -> IO Word8
+testFromChunksIOLaziness h = do
+    lbs <-
+        Lazy.fromChunksIO $
+        S.fromList (Strict.toArray (BS.singleton h) : undefined)
+    return $ BSL.head lbs
+
 main :: IO ()
 main =
-  hspec $ do
-    describe "Array tests" $ do
-      it "Strict fromArray" $
-        mapM_ (flip withSystemTempFile checkFileContent . show) ([1..100] :: [Int])
-      prop "Strict Identity" $ \bs ->
-        bs `shouldBe` Strict.fromArray (Strict.toArray bs)
-      prop "Lazy Identity" $ \bs -> do
-        bs2 <- Lazy.fromChunks . Lazy.toChunks $ bs
-        bs `shouldBe` bs2
-    wl0 <- runIO $ word8List 0
-    wlM <- runIO $ word8List 900
-    wlL <- runIO $ word8List 73700
-    describe "Strict: Fold tests" $ do
-      propFoldTestStrict wl0
-      propFoldTestStrict wlM
-      propFoldTestStrict wlL
-    describe "Strict: N Fold tests" $ do
-      propNFoldTestStrict 0 wl0
-      propNFoldTestStrict 900 wlM
-      propNFoldTestStrict 73700 wlL
-    describe "Strict: Unfold tests" $ do
-      propUnfoldTestStrict wl0
-      propUnfoldTestStrict wlM
-      propUnfoldTestStrict wlL
-    describe "Lazy: Unfold tests" $ do
-      propUnfoldTestLazy wl0
-      propUnfoldTestLazy wlM
-      propUnfoldTestLazy wlL
-    describe "Laziness of fromChunks" $ do
-      it "Should not fail" $ do
-        w <- testFromChunksLaziness 100
-        w `shouldBe` 100
+    hspec $ do
+        describe "Array tests" $ do
+            it "Strict fromArray" $
+                mapM_
+                    (flip withSystemTempFile checkFileContent . show)
+                    ([1 .. 100] :: [Int])
+            prop "Strict Identity" $ \bs ->
+                bs `shouldBe` Strict.fromArray (Strict.toArray bs)
+            prop "Lazy Identity" $ \bs -> do
+                bs2 <- Lazy.fromChunks . Lazy.toChunks $ bs
+                bs `shouldBe` bs2
+        wl0 <- runIO $ word8List 0
+        wlM <- runIO $ word8List 900
+        wlL <- runIO $ word8List 73700
+        describe "Strict: Fold tests" $ do
+            propFoldTestStrict wl0
+            propFoldTestStrict wlM
+            propFoldTestStrict wlL
+        describe "Strict: N Fold tests" $ do
+            propNFoldTestStrict 0 wl0
+            propNFoldTestStrict 900 wlM
+            propNFoldTestStrict 73700 wlL
+        describe "Strict: Unfold tests" $ do
+            propUnfoldTestStrict wl0
+            propUnfoldTestStrict wlM
+            propUnfoldTestStrict wlL
+        describe "Lazy: Unfold tests" $ do
+            propUnfoldTestLazy wl0
+            propUnfoldTestLazy wlM
+            propUnfoldTestLazy wlL
+        describe "Laziness of fromChunksIO" $ do
+            it "Should not fail" $ do
+                w <- testFromChunksIOLaziness 100
+                w `shouldBe` 100
+        describe "Correctness of fromChunks" propFromChunks
+        describe "Correctness of fromChunksIO" propFromChunksIO
