diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,7 @@
+0.0.11
+
+* Implement shuffling
+
 0.0.10
 
 * Relax bounds on semigroups
diff --git a/list-zipper.cabal b/list-zipper.cabal
--- a/list-zipper.cabal
+++ b/list-zipper.cabal
@@ -1,14 +1,15 @@
 name:               list-zipper
-version:            0.0.10
+version:            0.0.11
 license:            BSD3
 license-file:       LICENCE
-author:             Queensland Functional Programming Lab <oᴉ˙ldɟb@llǝʞsɐɥ>
-maintainer:         Queensland Functional Programming Lab <oᴉ˙ldɟb@llǝʞsɐɥ>
-copyright:          Copyright (c) 2018, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230.
+author:             Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>
+maintainer:         Tony Morris <ʇǝu˙sıɹɹoɯʇ@ןןǝʞsɐɥ>
+copyright:          Copyright (c) 2018-2019, Commonwealth Scientific and Industrial Research Organisation (CSIRO) ABN 41 687 119 230.
+                    Copyright (c) 2020-2021 Tony Morris
 synopsis:           A list zipper
 category:           Data
-description:       
-  <<https://raw.githubusercontent.com/qfpl/assets/master/data61-transparent-bg.png>>
+description:
+  <<https://system-f.gitlab.io/logo/systemf-450x450.jpg>>
   .
   A list zipper.
 homepage:           https://github.com/qfpl/list-zipper
@@ -30,6 +31,8 @@
                     , deriving-compat >= 0.5 && < 0.6
                     , lens >= 4 && < 5
                     , comonad >= 5.0 && < 6.0
+                    , MonadRandom >= 0.5 && < 1
+                    , random-shuffle >= 0.0.4 && < 1
                     , semigroupoids >=5.1 && <5.4
                     , semigroups >=0.16 && <0.20
                     , mtl >=2.2 && <2.3
@@ -39,7 +42,7 @@
                     -Wall
 
   default-extensions:
-  
+
                     NoImplicitPrelude
 
   hs-source-dirs:
@@ -64,17 +67,17 @@
                     , transformers >=0.4.1 && <5.5
                     , mtl >=2.2 && <2.3
 
-  type:             
+  type:
                     exitcode-stdio-1.0
 
-  main-is:          
+  main-is:
                     Tests.hs
 
-  hs-source-dirs:   
+  hs-source-dirs:
                     test
 
-  default-language: 
+  default-language:
                     Haskell2010
 
-  ghc-options:       
+  ghc-options:
                     -Wall
diff --git a/src/Data/ListZipper.hs b/src/Data/ListZipper.hs
--- a/src/Data/ListZipper.hs
+++ b/src/Data/ListZipper.hs
@@ -87,6 +87,7 @@
 , (<<.)
 , runListZipperOp
 , execListZipperOp
+, execListZipperOpOr
 , (##>)
 , (<##)
 , evalListZipperOp
@@ -99,18 +100,28 @@
 , ($$>)
 , (<$$)
 , opWhileJust
+-- * list zipper state operations
+, shuffleLeft
+, shuffleRight
+, shuffleListZipper
 ) where
 
+import System.Random.Shuffle
+import Control.Monad.Random.Class
+
+
 import Control.Applicative(Applicative(pure, (<*>)), Alternative((<|>), empty), (<*))
 import Control.Category((.), id)
 import Control.Comonad(Comonad(duplicate, extract))
 import Control.Lens(Each(each), Reversing(reversing), Ixed(ix), Rewrapped, Wrapped(Unwrapped, _Wrapped'), IxValue, Index, Prism', Lens', Traversal', _Wrapped, (^.), iso, (&), _1, _2)
+import Control.Monad
 import Control.Monad.Error.Class(MonadError(throwError, catchError))
 import Control.Monad.Fail(MonadFail(fail))
 import Control.Monad.Fix(MonadFix(mfix))
 import Control.Monad.Reader(MonadReader(ask, local, reader))
 import Control.Monad.State(MonadState(get, put, state))
 import qualified Control.Monad.Fail as Fail(fail)
+import Data.Foldable
 import Data.Traversable(Traversable(traverse))
 import Data.Semigroup.Traversable(Traversable1(traverse1))
 import Control.Monad(Monad((>>=), return), MonadPlus(mplus, mzero), (=<<))
@@ -132,11 +143,11 @@
 import Data.Ord(Ord((<)))
 import Data.Semigroup(Semigroup((<>)))
 import Data.Semigroup.Foldable(Foldable1(foldMap1))
-import Prelude(Show, (+))
+import Prelude(Show, (+), (-))
 import Text.Show.Deriving(deriveShow1)
 
 data ListZipper a =
-  ListZipper 
+  ListZipper
     [a]
     a
     [a]
@@ -231,7 +242,7 @@
 class AsListZipper z a | z -> a where
   _ListZipper ::
     Prism' z (ListZipper a)
-  
+
 instance AsListZipper (ListZipper a) a where
   _ListZipper =
     id
@@ -467,7 +478,7 @@
 
 instance Bind (ListZipperOp a) where
   ListZipperOp j >>- f =
-    ListZipperOp (\z -> 
+    ListZipperOp (\z ->
       j z >>- \(z', a) ->
       z' & f a ^. _Wrapped
       )
@@ -588,10 +599,10 @@
 getList =
   reader list
 
-mkListZipperOp :: 
+mkListZipperOp ::
   (ListZipper a -> Maybe b)
   -> ListZipperOp a b
-mkListZipperOp f = 
+mkListZipperOp f =
   get >>= liftListZipperOp . f
 
 (<$~) ::
@@ -610,7 +621,7 @@
 
 infixl 5 <$~
 
-(*>>) :: 
+(*>>) ::
   (ListZipper a -> Maybe b)
   -> ListZipperOp a c
   -> ListZipperOp a b
@@ -619,7 +630,7 @@
 
 infixl 5 *>>
 
-(<<*) :: 
+(<<*) ::
   ListZipperOp a c
   -> (ListZipper a -> Maybe b)
   -> ListZipperOp a b
@@ -631,7 +642,7 @@
 mkListZipperOp' ::
   (ListZipper a -> Maybe (ListZipper a))
   -> ListZipperOp' a
-mkListZipperOp' f = 
+mkListZipperOp' f =
   ListZipperOp (\s -> (\s' -> (s', ())) <$> f s)
 
 (.>>) ::
@@ -666,6 +677,13 @@
 execListZipperOp o =
   fmap (^. _1) . runListZipperOp o
 
+execListZipperOpOr ::
+  ListZipperOp a x
+  -> ListZipper a
+  -> ListZipper a
+execListZipperOpOr o =
+  fromMaybe <*> execListZipperOp o
+
 (##>) ::
   ListZipperOp a x
   -> ListZipper a
@@ -958,6 +976,39 @@
   -> ListZipperOp a a
 setFocus =
   modifyFocus . pure
+
+shuffleLeft ::
+  ListZipperOp' a
+shuffleLeft =
+  mkListZipperOp' (\z ->
+    case z of
+      ListZipper [] _ _ ->
+        Nothing
+      ListZipper (h:t) x r ->
+        Just (ListZipper t x (h:r))
+    )
+
+shuffleRight ::
+  ListZipperOp' a
+shuffleRight =
+  mkListZipperOp' (\z ->
+    case z of
+      ListZipper _ _ [] ->
+        Nothing
+      ListZipper l x (h:t) ->
+        Just (ListZipper (h:l) x t)
+  )
+
+shuffleListZipper ::
+  MonadRandom f =>
+  ListZipper a
+  -> f (ListZipper a)
+shuffleListZipper z =
+  let z' =
+        opWhileJust shuffleLeft z
+  in  do  i <- getRandomR (0, length z - 1)
+          z'' <- rightz shuffleM z'
+          pure (execListZipperOpOr (replicateM i shuffleRight) z'')
 
 deriveEq1 ''ListZipper
 deriveShow1 ''ListZipper
