diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,7 @@
 Changelog for Safe
 
+0.3.10
+    #15, add Safe cycle
 0.3.9
     #9, add Safe toEnum
 0.3.8
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright Neil Mitchell 2007-2015.
+Copyright Neil Mitchell 2007-2016.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/Safe.hs b/Safe.hs
--- a/Safe.hs
+++ b/Safe.hs
@@ -32,6 +32,7 @@
     foldl1May', foldl1Def', foldl1Note',
     scanl1May, scanl1Def, scanl1Note,
     scanr1May, scanr1Def, scanr1Note,
+    cycleMay, cycleDef, cycleNote,
     fromJustDef, fromJustNote,
     assertNote,
     atMay, atDef, atNote,
@@ -188,6 +189,15 @@
 scanr1Note, scanl1Note :: String -> (a -> a -> a) -> [a] -> [a]
 scanr1Note note = fromNote note "scanr1Note []" .^ scanr1May
 scanl1Note note = fromNote note "scanl1Note []" .^ scanl1May
+
+cycleMay :: [a] -> Maybe [a]
+cycleMay = liftMay null cycle
+
+cycleDef :: [a] -> [a] -> [a]
+cycleDef def = fromMaybe def . cycleMay
+
+cycleNote :: String -> [a] -> [a]
+cycleNote note = fromNote note "cycleNote []" . cycleMay
 
 -- | An alternative name for 'fromMaybe', to fit the naming scheme of this package.
 --   Generally using 'fromMaybe' directly would be considered better style.
diff --git a/safe.cabal b/safe.cabal
--- a/safe.cabal
+++ b/safe.cabal
@@ -1,17 +1,17 @@
-cabal-version:  >= 1.6
+cabal-version:  >= 1.18
 build-type:     Simple
 name:           safe
-version:        0.3.9
+version:        0.3.10
 license:        BSD3
 license-file:   LICENSE
 category:       Unclassified
 author:         Neil Mitchell <ndmitchell@gmail.com>
 maintainer:     Neil Mitchell <ndmitchell@gmail.com>
-copyright:      Neil Mitchell 2007-2015
+copyright:      Neil Mitchell 2007-2016
 homepage:       https://github.com/ndmitchell/safe#readme
 synopsis:       Library of safe (exception free) functions
 bug-reports:    https://github.com/ndmitchell/safe/issues
-tested-with:    GHC==7.10.1, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2, GHC==7.2.2
+tested-with:    GHC==8.0.1, GHC==7.10.3, GHC==7.8.4, GHC==7.6.3, GHC==7.4.2
 description:
     A library wrapping @Prelude@/@Data.List@ functions that can throw exceptions, such as @head@ and @!!@.
     Each unsafe function has up to four variants, e.g. with @tail@:
@@ -33,7 +33,7 @@
     * "Safe.Foldable" contains safe variants of @Foldable@ functions.
     .
     * "Safe.Exact" creates crashing versions of functions like @zip@ (errors if the lists are not equal) and @take@ (errors if there are not enough elements), then wraps them to provide safe variants.
-extra-source-files:
+extra-doc-files:
     CHANGES.txt
     README.md
 
@@ -42,6 +42,7 @@
     location: https://github.com/ndmitchell/safe.git
 
 library
+    default-language: Haskell2010
     build-depends:
         base < 5
 
