diff --git a/Changelog.md b/Changelog.md
--- a/Changelog.md
+++ b/Changelog.md
@@ -2,6 +2,10 @@
 
 <!-- See rendered changelog at https://streamly.composewell.com -->
 
+## 0.8.1.1 (Dec 2021)
+
+* Disable building FileSystem.Events where FS Events isn't supported.
+
 ## 0.8.1 (Nov 2021)
 
 See docs/API-changelog.txt for new APIs introduced.
diff --git a/benchmark/bench-report/bin/bench-runner.sh b/benchmark/bench-report/bin/bench-runner.sh
--- a/benchmark/bench-report/bin/bench-runner.sh
+++ b/benchmark/bench-report/bin/bench-runner.sh
@@ -34,7 +34,7 @@
   echo "       [--with-compiler <compiler exe name>]"
   echo "       [--cabal-build-options <options>]"
   echo "       [--rtsopts <opts>]"
-  echo "       [--commit-compare] [--base <commit>] [--candidate <commit>]"
+  #echo "       [--commit-compare] [--base <commit>] [--candidate <commit>]"
   #echo "       -- <gauge options or benchmarks>"
   echo
   echo "--benchmarks: benchmarks to run, use 'help' for list of benchmarks"
@@ -56,10 +56,10 @@
   echo "bench.sh --benchmarks Data.Parser -- Data.Parser/o-1-space "
   echo "restricts Heap/Stack space for O(1) characterstics"
   echo
-  echo "When using --commit-compare, by default comparative chart of HEAD^ vs HEAD"
-  echo "commit is generated, in the 'charts' directory."
-  echo "Use --base and --candidate to select the commits to compare."
-  echo
+  #echo "When using --commit-compare, by default comparative chart of HEAD^ vs HEAD"
+  #echo "commit is generated, in the 'charts' directory."
+  #echo "Use --base and --candidate to select the commits to compare."
+  #echo
   #echo "Any arguments after a '--' are passed directly to gauge"
   exit
 }
@@ -383,16 +383,20 @@
     fi
     echo "Comparing baseline commit [$BASE] with candidate [$CANDIDATE]"
     echo "Checking out base commit [$BASE] for benchmarking"
+    # XXX git checkout will overwrite this script itself and the scripts
+    # imported/used by this script.
     git checkout "$BASE" || die "Checkout of base commit [$BASE] failed"
 
-    $BUILD_BENCH || die "build failed"
+    # $BUILD_BENCH || die "build failed"
+    run_build "$BUILD_BENCH" $BENCHMARK_PACKAGE_NAME bench "$TARGETS"
     run_bench_targets $BENCHMARK_PACKAGE_NAME b "$bench_list" target_exe_extra_args
 
     echo "Checking out candidate commit [$CANDIDATE] for benchmarking"
     git checkout "$CANDIDATE" || \
         die "Checkout of candidate [$CANDIDATE] commit failed"
 
-    $BUILD_BENCH || die "build failed"
+    # $BUILD_BENCH || die "build failed"
+    run_build "$BUILD_BENCH" $BENCHMARK_PACKAGE_NAME bench "$TARGETS"
     run_bench_targets $BENCHMARK_PACKAGE_NAME b "$bench_list" target_exe_extra_args
     # XXX reset back to the original commit
 }
@@ -417,6 +421,7 @@
 
   if test "$COMMIT_COMPARE" = "0"
   then
+    run_build "$BUILD_BENCH" $BENCHMARK_PACKAGE_NAME bench "$TARGETS"
     run_bench_targets $BENCHMARK_PACKAGE_NAME b "$bench_list" target_exe_extra_args
   else
     run_benches_comparing "$bench_list"
@@ -501,6 +506,8 @@
     --sort-by-name) SORT_BY_NAME=1; shift ;;
     --graphs) GRAPH=1; shift ;;
     --no-measure) MEASURE=0; shift ;;
+    # This is used in build-lib.sh to enable dev_build function which is used
+    # in targets.sh to enable or disable some targets.
     --dev-build) RUNNING_DEVBUILD=1; shift ;;
     --use-nix) USE_NIX=1; shift ;;
     --use-gauge) USE_GAUGE=1; shift ;;
@@ -613,7 +620,6 @@
 BUILD_BENCH="$CABAL_EXECUTABLE v2-build $BUILD_FLAGS $CABAL_BUILD_OPTIONS --enable-benchmarks"
 if test "$MEASURE" = "1"
 then
-  run_build "$BUILD_BENCH" $BENCHMARK_PACKAGE_NAME bench "$TARGETS"
   run_measurements "$TARGETS"
 fi
 
diff --git a/bin/mk-hscope.sh b/bin/mk-hscope.sh
--- a/bin/mk-hscope.sh
+++ b/bin/mk-hscope.sh
@@ -1,7 +1,7 @@
 #!/usr/bin/env bash
 
 GHC_VERSION=8.10.4
-STREAMLY_VERSION=0.8.1
+STREAMLY_VERSION=0.8.1.1
 
 case `uname` in
   Darwin) SYSTEM=x86_64-osx;;
diff --git a/bin/test.sh b/bin/test.sh
--- a/bin/test.sh
+++ b/bin/test.sh
@@ -2,7 +2,7 @@
 
 SCRIPT_DIR=$(dirname $0)
 
-STREAMLY_VERSION=0.8.1
+STREAMLY_VERSION=0.8.1.1
 BENCH_REPORT_DIR=benchmark/bench-report
 source $SCRIPT_DIR/targets.sh
 
@@ -239,7 +239,9 @@
     fi
   done
 
-  hpc sum --output=$ALLTIX $TIXFILES
+  #echo "Combining tix files:"
+  #echo $TIXFILES | tr ' ' '\n'
+  hpc sum --union --output=$ALLTIX $TIXFILES
   run_verbose hpc markup $ALLTIX --hpcdir $MIX_DIR
   run_verbose hpc report $ALLTIX $HPC_REPORT_OPTIONS --hpcdir $MIX_DIR
 fi
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -1,6 +1,6 @@
 #! /bin/sh
 # Guess values for system-dependent variables and create Makefiles.
-# Generated by GNU Autoconf 2.71 for streamly 0.8.1.
+# Generated by GNU Autoconf 2.71 for streamly 0.8.1.1.
 #
 # Report bugs to <streamly@composewell.com>.
 #
@@ -610,8 +610,8 @@
 # Identity of this package.
 PACKAGE_NAME='streamly'
 PACKAGE_TARNAME='streamly'
-PACKAGE_VERSION='0.8.1'
-PACKAGE_STRING='streamly 0.8.1'
+PACKAGE_VERSION='0.8.1.1'
+PACKAGE_STRING='streamly 0.8.1.1'
 PACKAGE_BUGREPORT='streamly@composewell.com'
 PACKAGE_URL='https://streamly.composewell.com'
 
@@ -1256,7 +1256,7 @@
   # Omit some internal or obsolete options to make the list less imposing.
   # This message is too long to be a string in the A/UX 3.1 sh.
   cat <<_ACEOF
-\`configure' configures streamly 0.8.1 to adapt to many kinds of systems.
+\`configure' configures streamly 0.8.1.1 to adapt to many kinds of systems.
 
 Usage: $0 [OPTION]... [VAR=VALUE]...
 
@@ -1318,7 +1318,7 @@
 
 if test -n "$ac_init_help"; then
   case $ac_init_help in
-     short | recursive ) echo "Configuration of streamly 0.8.1:";;
+     short | recursive ) echo "Configuration of streamly 0.8.1.1:";;
    esac
   cat <<\_ACEOF
 
@@ -1404,7 +1404,7 @@
 test -n "$ac_init_help" && exit $ac_status
 if $ac_init_version; then
   cat <<\_ACEOF
-streamly configure 0.8.1
+streamly configure 0.8.1.1
 generated by GNU Autoconf 2.71
 
 Copyright (C) 2021 Free Software Foundation, Inc.
@@ -1674,7 +1674,7 @@
 This file contains any messages produced by compilers while
 running configure, to aid debugging if configure makes a mistake.
 
-It was created by streamly $as_me 0.8.1, which was
+It was created by streamly $as_me 0.8.1.1, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   $ $0$ac_configure_args_raw
@@ -4028,7 +4028,7 @@
 # report actual input values of CONFIG_FILES etc. instead of their
 # values after options handling.
 ac_log="
-This file was extended by streamly $as_me 0.8.1, which was
+This file was extended by streamly $as_me 0.8.1.1, which was
 generated by GNU Autoconf 2.71.  Invocation command line was
 
   CONFIG_FILES    = $CONFIG_FILES
@@ -4084,7 +4084,7 @@
 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
 ac_cs_config='$ac_cs_config_escaped'
 ac_cs_version="\\
-streamly config.status 0.8.1
+streamly config.status 0.8.1.1
 configured by $0, generated by GNU Autoconf 2.71,
   with options \\"\$ac_cs_config\\"
 
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@
 # See https://www.gnu.org/software/autoconf/manual/autoconf.html for help on
 # the macros used in this file.
 
-AC_INIT([streamly], [0.8.1], [streamly@composewell.com], [streamly], [https://streamly.composewell.com])
+AC_INIT([streamly], [0.8.1.1], [streamly@composewell.com], [streamly], [https://streamly.composewell.com])
 
 # To suppress "WARNING: unrecognized options: --with-compiler"
 AC_ARG_WITH([compiler], [GHC])
diff --git a/dev/MAINTAINING.md b/dev/MAINTAINING.md
--- a/dev/MAINTAINING.md
+++ b/dev/MAINTAINING.md
@@ -193,11 +193,11 @@
 of the issue. If no change is required the issue must have one of the
 following labels:
 
-* invalid
-* question
-* discussion
-* duplicate
-* wontfix
+* disposition:invalid
+* disposition:question
+* disposition:discussion
+* disposition:duplicate
+* disposition:wontfix
 
 If a change is required we need to do level-2 triage of the issue, see the
 sections below.
@@ -207,12 +207,13 @@
 When a change is required we need to put one of the __change type__
 labels as part of level-2 triaging:
 
-* performance: User visible impact on performance.
-* usability: It is not convenient to use the library.
-* documentation: documentation is not correct or sufficient.
-* bug: A functionality issue, not working as expected.
-* enhancement: A new feature or enhancement of the product.
-* maintenance: A refactor or any other change with no user visible impact.
+* type:performance: User visible impact on performance.
+* type:testing: Improves testing or related to testing.
+* type:usability: It is not convenient to use the library.
+* type:documentation: documentation is not correct or sufficient.
+* type:bug: A functionality issue, not working as expected.
+* type:enhancement: includes a new feature or enhancement
+* type:maintenance: A refactor or any other change with no user visible impact.
 
 ### Aspect
 
@@ -229,13 +230,13 @@
 
 * severity:high
 
-### Change impact
+### API impact
 
 For a user visible issue whether it has a release/changelog impact:
 
-* enhancement: includes a new feature or enhancement
-* breaking: has a breaking impact on existing deployments
-* deprecating: deprecates an existing functionality
+* api:new: includes a new feature or enhancement
+* api:breaking: has a breaking impact on existing deployments
+* api:deprecating: deprecates an existing functionality
 
 __RULE__: Any commit that may affect the end user in some way MUST have
 either a changelog entry OR MUST have an issue marked with one of the
@@ -253,9 +254,13 @@
 If the issue is assigned to someone then it is considered scheduled. Otherwise
 it is unscheduled.  Unassigned issues may have the following labels:
 
-* deferred: blocked on any other fix or a decision to be made, or deliberately
-  deferred for some reason.
+* sched:deferred: deliberately deferred for some reason.
+* sched:blocked: blocked on any other fix or a decision to be mad
+
+### For Contributors
+
 * help-wanted: anyone can take the issue and contribute
+* good-first-issue: good for new contributors
 
 ## Correlating Changes, Issues and Releases
 
diff --git a/docs/CONTRIBUTORS.md b/docs/CONTRIBUTORS.md
--- a/docs/CONTRIBUTORS.md
+++ b/docs/CONTRIBUTORS.md
@@ -4,6 +4,11 @@
 Use `git shortlog -sn tag1...tag2` on the git repository to get a list of
 contributors between two repository tags.
 
+## 0.8.1.1
+
+* Harendra Kumar
+* Julian Ospald
+
 ## 0.8.1
 
 * Harendra Kumar
diff --git a/docs/getting-started.md b/docs/getting-started.md
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -204,7 +204,7 @@
 adding a version number constraint to the `--build-depends` flag:
 
 ```
-$ cabal repl --build-depends streamly==0.8.1
+$ cabal repl --build-depends streamly==0.8.1.1
 [1 of 1] Compiling Main             ( Main.hs, interpreted )
 Ok, modules loaded: Main.
 *Main>
diff --git a/src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs b/src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs
--- a/src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs
+++ b/src/Streamly/Internal/Data/Array/Foreign/Mut/Type.hs
@@ -703,13 +703,12 @@
 -------------------------------------------------------------------------------
 
 -- XXX We can possibly use a smallMutableByteArray to hold the start, end,
--- bound pointers. Or we can use the first 16 bytes of the allocation to store
--- the end, bound pointers. Using fully mutable handle will ensure that we do
--- not have multiple references to the same array of different lengths lying
--- around and potentially misused. In that case "snoc" need not return a new
--- array (snoc :: Array a -> a -> m ()), it will just modify the old reference.
--- The array length will be mutable.  This means the length function would also
--- be monadic.  Mutable arrays would behave more like files that grow in that
+-- bound pointers.  Using fully mutable handle will ensure that we do not have
+-- multiple references to the same array of different lengths lying around and
+-- potentially misused. In that case "snoc" need not return a new array (snoc
+-- :: Array a -> a -> m ()), it will just modify the old reference.  The array
+-- length will be mutable.  This means the length function would also be
+-- monadic.  Mutable arrays would behave more like files that grow in that
 -- case.
 
 -- | Snoc using a 'Ptr'. Low level reusable function.
@@ -846,6 +845,9 @@
 -- Resizing
 -------------------------------------------------------------------------------
 
+-- XXX See if resizing can be implemented by reading the old array as a stream
+-- and then using writeN to the new array.
+--
 -- | Reallocate the array to the specified size in bytes. If the size is less
 -- than the original array the array gets truncated.
 {-# NOINLINE reallocAligned #-}
@@ -925,6 +927,8 @@
 -- Reducing the length
 -------------------------------------------------------------------------------
 
+-- XXX Either slice the array or stream it and write it out to a new array?
+--
 -- | Drop the last n elements of the array to reduce the length by n. The
 -- capacity is reallocated using the user supplied function.
 --
diff --git a/src/Streamly/Internal/Ring/Foreign.hs b/src/Streamly/Internal/Ring/Foreign.hs
--- a/src/Streamly/Internal/Ring/Foreign.hs
+++ b/src/Streamly/Internal/Ring/Foreign.hs
@@ -6,45 +6,94 @@
 -- Stability   : experimental
 -- Portability : GHC
 --
+-- A ring array is a circular mutable array.
 
+-- XXX Write benchmarks
+-- XXX Make the implementation similar to mutable array
+-- XXX Rename this module to Data.RingArray.Storable
+
 module Streamly.Internal.Ring.Foreign
-    ( Ring(..)
+    (
+    -- * Type
+    Ring(..)
 
     -- * Construction
     , new
+    , newRing
+    , writeN
+
     , advance
     , moveBy
     , startOf
 
-    -- * Modification
+    -- * Random writes
     , unsafeInsert
+    , slide
+    , putIndex
+    , modifyIndex
 
+    -- * Unfolds
+    , read
+    , readRev
+
+    -- * Random reads
+    , getIndex
+    , getIndexUnsafe
+    , getIndexRev
+
+    -- * Size
+    , length
+    , byteLength
+    -- , capacity
+    , byteCapacity
+    , bytesFree
+
+    -- * Casting
+    , cast
+    , castUnsafe
+    , asBytes
+    , fromArray
+
     -- * Folds
     , unsafeFoldRing
     , unsafeFoldRingM
     , unsafeFoldRingFullM
     , unsafeFoldRingNM
 
+    -- * Stream of Arrays
+    , ringsOf
+
     -- * Fast Byte Comparisons
     , unsafeEqArray
     , unsafeEqArrayN
     ) where
 
+#include "inline.hs"
+
 import Control.Exception (assert)
+import Control.Monad.IO.Class (MonadIO(..))
+import Data.Word (Word8)
 import Foreign.ForeignPtr (ForeignPtr, withForeignPtr, touchForeignPtr)
 import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
 import Foreign.Ptr (plusPtr, minusPtr, castPtr)
 import Foreign.Storable (Storable(..))
 import GHC.ForeignPtr (mallocPlainForeignPtrAlignedBytes)
 import GHC.Ptr (Ptr(..))
-import Prelude hiding (length, concat)
-
-import Control.Monad.IO.Class (MonadIO(..))
-import Streamly.Internal.Data.Array.Foreign.Mut.Type (memcmp)
+import Streamly.Internal.Data.Array.Foreign.Mut.Type (Array, memcmp)
+import Streamly.Internal.Data.Fold.Type (Fold(..))
+import Streamly.Internal.Data.Stream.Serial (SerialT(..))
+-- import Streamly.Internal.Data.Stream.IsStream.Transform (scan)
+import Streamly.Internal.Data.Unfold.Type (Unfold(..))
 import Streamly.Internal.System.IO (unsafeInlineIO)
 
 import qualified Streamly.Internal.Data.Array.Foreign.Type as A
 
+import Prelude hiding (length, concat, read)
+
+-- $setup
+-- >>> :m
+-- >>> import qualified Streamly.Internal.Ring.Foreign as Ring
+
 -- | A ring buffer is a mutable array of fixed size. Initially the array is
 -- empty, with ringStart pointing at the start of allocated memory. We call the
 -- next location to be written in the ring as ringHead. Initially ringHead ==
@@ -62,6 +111,10 @@
     , ringBound :: {-# UNPACK #-} !(Ptr a)        -- first address beyond allocated memory
     }
 
+-------------------------------------------------------------------------------
+-- Construction
+-------------------------------------------------------------------------------
+
 -- | Get the first address of the ring as a pointer.
 startOf :: Ring a -> Ptr a
 startOf = unsafeForeignPtrToPtr . ringStart
@@ -79,6 +132,17 @@
         , ringBound = p `plusPtr` size
         }, p)
 
+-- XXX Rename this to "new".
+--
+-- | @newRing count@ allocates an empty array that can hold 'count' items.  The
+-- memory of the array is uninitialized and the allocation is aligned as per
+-- the 'Storable' instance of the type.
+--
+-- /Unimplemented/
+{-# INLINE newRing #-}
+newRing :: Int -> m (Ring a)
+newRing = undefined
+
 -- | Advance the ringHead by 1 item, wrap around if we hit the end of the
 -- array.
 {-# INLINE advance #-}
@@ -106,6 +170,47 @@
     off = assert (offInBytes `mod` elemSize == 0) $ offInBytes `div` elemSize
     advanceFromHead = (off + by `mod` len) * elemSize
 
+-- XXX Move the writeLastN from array module here.
+--
+-- | @writeN n@ is a rolling fold that keeps the last n elements of the stream
+-- in a ring array.
+--
+-- /Unimplemented/
+{-# INLINE writeN #-}
+writeN :: -- (Storable a, MonadIO m) =>
+    Int -> Fold m a (Ring a)
+writeN = undefined
+
+-------------------------------------------------------------------------------
+-- Conversions
+-------------------------------------------------------------------------------
+
+-- | Cast a mutable array to a ring array.
+fromArray :: Array a -> Ring a
+fromArray = undefined
+
+-------------------------------------------------------------------------------
+-- Conversion to/from array
+-------------------------------------------------------------------------------
+
+-- | Modify a given index of a ring array using a modifier function.
+--
+-- /Unimplemented/
+modifyIndex :: -- forall m a b. (MonadIO m, Storable a) =>
+    Ring a -> Int -> (a -> (a, b)) -> m b
+modifyIndex = undefined
+
+-- | /O(1)/ Write the given element at the given index in the ring array.
+-- Performs in-place mutation of the array.
+--
+-- >>> putIndex arr ix val = Ring.modifyIndex arr ix (const (val, ()))
+--
+-- /Unimplemented/
+{-# INLINE putIndex #-}
+putIndex :: -- (MonadIO m, Storable a) =>
+    Ring a -> Int -> a -> m ()
+putIndex = undefined
+
 -- | Insert an item at the head of the ring, when the ring is full this
 -- replaces the oldest item in the ring with the new item. This is unsafe
 -- beause ringHead supplied is not verified to be within the Ring. Also,
@@ -117,6 +222,155 @@
     -- touchForeignPtr (ringStart rb)
     return $ advance rb ringHead
 
+-- | Insert an item at the head of the ring, when the ring is full this
+-- replaces the oldest item in the ring with the new item.
+--
+-- /Unimplemented/
+slide :: -- forall m a. (MonadIO m, Storable a) =>
+    Ring a -> a -> m (Ring a)
+slide = undefined
+
+-------------------------------------------------------------------------------
+-- Random reads
+-------------------------------------------------------------------------------
+
+-- | Return the element at the specified index without checking the bounds.
+--
+-- Unsafe because it does not check the bounds of the ring array.
+{-# INLINE_NORMAL getIndexUnsafe #-}
+getIndexUnsafe :: -- forall m a. (MonadIO m, Storable a) =>
+    Ring a -> Int -> m a
+getIndexUnsafe = undefined
+
+-- | /O(1)/ Lookup the element at the given index. Index starts from 0.
+--
+{-# INLINE getIndex #-}
+getIndex :: -- (MonadIO m, Storable a) =>
+    Ring a -> Int -> m a
+getIndex = undefined
+
+-- | /O(1)/ Lookup the element at the given index from the end of the array.
+-- Index starts from 0.
+--
+-- Slightly faster than computing the forward index and using getIndex.
+--
+{-# INLINE getIndexRev #-}
+getIndexRev :: -- (MonadIO m, Storable a) =>
+    Ring a -> Int -> m a
+getIndexRev = undefined
+
+-------------------------------------------------------------------------------
+-- Size
+-------------------------------------------------------------------------------
+
+-- | /O(1)/ Get the byte length of the array.
+--
+-- /Unimplemented/
+{-# INLINE byteLength #-}
+byteLength :: Ring a -> Int
+byteLength = undefined
+
+-- | /O(1)/ Get the length of the array i.e. the number of elements in the
+-- array.
+--
+-- Note that 'byteLength' is less expensive than this operation, as 'length'
+-- involves a costly division operation.
+--
+-- /Unimplemented/
+{-# INLINE length #-}
+length :: -- forall a. Storable a =>
+    Ring a -> Int
+length = undefined
+
+-- | Get the total capacity of an array. An array may have space reserved
+-- beyond the current used length of the array.
+--
+-- /Pre-release/
+{-# INLINE byteCapacity #-}
+byteCapacity :: Ring a -> Int
+byteCapacity = undefined
+
+-- | The remaining capacity in the array for appending more elements without
+-- reallocation.
+--
+-- /Pre-release/
+{-# INLINE bytesFree #-}
+bytesFree :: Ring a -> Int
+bytesFree = undefined
+
+-------------------------------------------------------------------------------
+-- Unfolds
+-------------------------------------------------------------------------------
+
+-- | Unfold a ring array into a stream.
+--
+-- /Unimplemented/
+{-# INLINE_NORMAL read #-}
+read :: -- forall m a. (MonadIO m, Storable a) =>
+    Unfold m (Ring a) a
+read = undefined
+
+-- | Unfold a ring array into a stream in reverse order.
+--
+-- /Unimplemented/
+{-# INLINE_NORMAL readRev #-}
+readRev :: -- forall m a. (MonadIO m, Storable a) =>
+    Unfold m (Array a) a
+readRev = undefined
+
+-------------------------------------------------------------------------------
+-- Stream of arrays
+-------------------------------------------------------------------------------
+
+-- XXX Move this module to a lower level Ring/Type module and move ringsOf to a
+-- higher level ring module where we can import "scan".
+
+-- | @ringsOf n stream@ groups the input stream into a stream of
+-- ring arrays of size n. Each ring is a sliding window of size n.
+--
+-- /Unimplemented/
+{-# INLINE_NORMAL ringsOf #-}
+ringsOf :: -- forall m a. (MonadIO m, Storable a) =>
+    Int -> SerialT m a -> SerialT m (Array a)
+ringsOf = undefined -- Stream.scan (writeN n)
+
+-------------------------------------------------------------------------------
+-- Casting
+-------------------------------------------------------------------------------
+
+-- | Cast an array having elements of type @a@ into an array having elements of
+-- type @b@. The array size must be a multiple of the size of type @b@.
+--
+-- /Unimplemented/
+--
+castUnsafe :: Ring a -> Ring b
+castUnsafe = undefined
+
+-- | Cast an @Array a@ into an @Array Word8@.
+--
+-- /Unimplemented/
+--
+asBytes :: Ring a -> Ring Word8
+asBytes = castUnsafe
+
+-- | Cast an array having elements of type @a@ into an array having elements of
+-- type @b@. The length of the array should be a multiple of the size of the
+-- target element otherwise 'Nothing' is returned.
+--
+-- /Pre-release/
+--
+cast :: forall a b. Storable b => Ring a -> Maybe (Ring b)
+cast arr =
+    let len = byteLength arr
+        r = len `mod` sizeOf (undefined :: b)
+     in if r /= 0
+        then Nothing
+        else Just $ castUnsafe arr
+
+-------------------------------------------------------------------------------
+-- Equality
+-------------------------------------------------------------------------------
+
 -- XXX remove all usage of unsafeInlineIO
 --
 -- | Like 'unsafeEqArray' but compares only N bytes instead of entire length of
@@ -166,6 +420,11 @@
             return (r1 && r2)
     in res
 
+-------------------------------------------------------------------------------
+-- Folding
+-------------------------------------------------------------------------------
+
+-- XXX We can unfold it into a stream and fold the stream instead.
 -- XXX use MonadIO
 --
 -- | Fold the buffer starting from ringStart up to the given 'Ptr' using a pure
diff --git a/streamly.cabal b/streamly.cabal
--- a/streamly.cabal
+++ b/streamly.cabal
@@ -1,6 +1,6 @@
 cabal-version:      2.2
 name:               streamly
-version:            0.8.1
+version:            0.8.1.1
 synopsis:           Dataflow programming and declarative concurrency
 description:
   Browse the documentation at https://streamly.composewell.com.
@@ -331,6 +331,9 @@
     if os(linux)
       exposed-modules: Streamly.Internal.FileSystem.Event.Linux
 
+    if os(linux) || os(darwin) || os(windows)
+      exposed-modules: Streamly.Internal.FileSystem.Event
+
     hs-source-dirs:    src
     other-modules:
                        Streamly.Data.Array
@@ -505,7 +508,6 @@
                      , Streamly.Internal.FileSystem.File
                      , Streamly.Internal.FileSystem.FDIO
                      , Streamly.Internal.FileSystem.FD
-                     , Streamly.Internal.FileSystem.Event
 
                      -- streamly-console
                      , Streamly.Internal.Console.Stdio
