diff --git a/CHANGES.txt b/CHANGES.txt
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,5 +1,9 @@
 Changelog for Extra
 
+1.5.1
+    #25, add zipFrom and zipWithFrom
+    #24, add eitherToMaybe and maybeToEither
+    Add fromLeft' and fromRight'
 1.5
     Change fromLeft/fromRight signatures to follow the base libraries
 1.4.12
diff --git a/extra.cabal b/extra.cabal
--- a/extra.cabal
+++ b/extra.cabal
@@ -1,7 +1,7 @@
-cabal-version:      >= 1.10
+cabal-version:      >= 1.18
 build-type:         Simple
 name:               extra
-version:            1.5
+version:            1.5.1
 license:            BSD3
 license-file:       LICENSE
 category:           Development
diff --git a/src/Data/Either/Extra.hs b/src/Data/Either/Extra.hs
--- a/src/Data/Either/Extra.hs
+++ b/src/Data/Either/Extra.hs
@@ -6,7 +6,9 @@
 --   partial, and should be used with care in production-quality code.
 module Data.Either.Extra(
     module Data.Either,
-    isLeft, isRight, fromLeft, fromRight, fromEither
+    isLeft, isRight, fromLeft, fromRight, fromEither,
+    fromLeft', fromRight',
+    eitherToMaybe, maybeToEither,
     ) where
 
 import Data.Either
@@ -32,6 +34,28 @@
 
 #endif
 
+
+-- | The 'fromLeft'' function extracts the element out of a 'Left' and
+--   throws an error if its argument is 'Right'.
+--   Much like 'fromJust', using this function in polished code is usually a bad idea.
+--
+-- > \x -> fromLeft' (Left  x) == x
+-- > \x -> fromLeft' (Right x) == undefined
+fromLeft' :: Either l r -> l
+fromLeft' (Left x) = x
+fromLeft' _ = error "fromLeft', given a Right"
+
+-- | The 'fromRight'' function extracts the element out of a 'Right' and
+--   throws an error if its argument is 'Left'.
+--   Much like 'fromJust', using this function in polished code is usually a bad idea.
+--
+-- > \x -> fromRight' (Right x) == x
+-- > \x -> fromRight' (Left  x) == undefined
+fromRight' :: Either l r -> r
+fromRight' (Right x) = x
+fromRight' _ = error "fromRight', given a Left"
+
+
 #if __GLASGOW_HASKELL__ < 708
 -- | Test if an 'Either' value is the 'Left' constructor.
 --   Provided as standard with GHC 7.8 and above.
@@ -51,3 +75,20 @@
 -- > \x -> fromEither (Right x) == x
 fromEither :: Either a a -> a
 fromEither = either id id
+
+
+-- | Given a 'Maybe', convert it to an 'Either', providing a suitable
+--   value for the 'Left' should the value be 'Nothing'.
+--
+-- > \a b -> maybeToEither a (Just b) == Right b
+-- > \a -> maybeToEither a Nothing == Left a
+maybeToEither :: a -> Maybe b -> Either a b
+maybeToEither a (Just b) = Right b
+maybeToEither a Nothing = Left a
+
+-- | Given an 'Either', convert it to a 'Maybe', where 'Left' becomes 'Nothing'.
+--
+-- > \x -> eitherToMaybe (Left x) == Nothing
+-- > \x -> eitherToMaybe (Right x) == Just x
+eitherToMaybe :: Either a b -> Maybe b
+eitherToMaybe = either (const Nothing) Just
diff --git a/src/Data/List/Extra.hs b/src/Data/List/Extra.hs
--- a/src/Data/List/Extra.hs
+++ b/src/Data/List/Extra.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP, TupleSections #-}
+{-# LANGUAGE CPP, TupleSections, BangPatterns #-}
 {-# OPTIONS_GHC -fno-warn-duplicate-exports #-}
 
 -- | This module extends "Data.List" with extra functions of a similar nature.
@@ -24,6 +24,7 @@
     disjoint, allSame, anySame,
     repeatedly, for, firstJust,
     concatUnzip, concatUnzip3,
+    zipFrom, zipWithFrom,
     replace, merge, mergeBy,
     ) where
 
@@ -171,6 +172,25 @@
 splitAtEnd i xs = f xs (drop i xs)
     where f (x:xs) (y:ys) = first (x:) $ f xs ys
           f xs _ = ([], xs)
+
+
+-- | 'zip' against an enumeration.
+--   Never truncates the output - raises an error if the enumeration runs out.
+--
+-- > \i xs -> zip [i..] xs == zipFrom i xs
+-- > zipFrom False [1..3] == undefined
+zipFrom :: Enum a => a -> [b] -> [(a, b)]
+zipFrom = zipWithFrom (,)
+
+-- | 'zipFrom' generalised to any combining operation.
+--
+-- > \i xs -> zipWithFrom (,) i xs == zipFrom i xs
+zipWithFrom :: Enum a => (a -> b -> c) -> a -> [b] -> [c]
+zipWithFrom f a xs = go a xs
+    where
+        -- if we aren't strict in the accumulator, it's highly like to be a space leak
+        go !a [] = []
+        go !a (x:xs) = f a x : go (succ a) xs
 
 
 -- | A merging of 'unzip' and 'concat'.
diff --git a/src/Extra.hs b/src/Extra.hs
--- a/src/Extra.hs
+++ b/src/Extra.hs
@@ -17,13 +17,13 @@
     whenJust, whenJustM, unit, maybeM, eitherM, loopM, whileM, partitionM, concatMapM, concatForM, mconcatMapM, mapMaybeM, findM, firstJustM, whenM, unlessM, ifM, notM, (||^), (&&^), orM, andM, anyM, allM,
     -- * Data.Either.Extra
     -- | Extra functions available in @"Data.Either.Extra"@.
-    isLeft, isRight, fromLeft, fromRight, fromEither,
+    isLeft, isRight, fromLeft, fromRight, fromEither, fromLeft', fromRight', eitherToMaybe, maybeToEither,
     -- * Data.IORef.Extra
     -- | Extra functions available in @"Data.IORef.Extra"@.
     modifyIORef', writeIORef', atomicModifyIORef', atomicWriteIORef, atomicWriteIORef',
     -- * Data.List.Extra
     -- | Extra functions available in @"Data.List.Extra"@.
-    lower, upper, trim, trimStart, trimEnd, word1, line1, dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd, dropWhileEnd, dropWhileEnd', takeWhileEnd, stripSuffix, stripInfix, stripInfixEnd, wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, list, uncons, unsnoc, cons, snoc, drop1, mconcatMap, groupSort, groupSortOn, groupSortBy, nubOrd, nubOrdBy, nubOrdOn, nubOn, groupOn, sortOn, disjoint, allSame, anySame, repeatedly, for, firstJust, concatUnzip, concatUnzip3, replace, merge, mergeBy,
+    lower, upper, trim, trimStart, trimEnd, word1, line1, dropEnd, takeEnd, splitAtEnd, breakEnd, spanEnd, dropWhileEnd, dropWhileEnd', takeWhileEnd, stripSuffix, stripInfix, stripInfixEnd, wordsBy, linesBy, breakOn, breakOnEnd, splitOn, split, chunksOf, list, uncons, unsnoc, cons, snoc, drop1, mconcatMap, groupSort, groupSortOn, groupSortBy, nubOrd, nubOrdBy, nubOrdOn, nubOn, groupOn, sortOn, disjoint, allSame, anySame, repeatedly, for, firstJust, concatUnzip, concatUnzip3, zipFrom, zipWithFrom, replace, merge, mergeBy,
     -- * Data.Tuple.Extra
     -- | Extra functions available in @"Data.Tuple.Extra"@.
     first, second, (***), (&&&), dupe, both, fst3, snd3, thd3,
diff --git a/src/System/Time/Extra.hs b/src/System/Time/Extra.hs
--- a/src/System/Time/Extra.hs
+++ b/src/System/Time/Extra.hs
@@ -17,7 +17,6 @@
 import Data.Time.Clock
 import System.Clock
 import Numeric.Extra
-import Data.IORef
 import Control.Monad.Extra
 import Control.Exception.Extra
 import Data.Typeable
@@ -73,6 +72,7 @@
                             (\_ -> fmap Just f))
 
 
+-- Once we remove subtractTime we can remove the dependency on the time package entire.
 {-# DEPRECATED subtractTime "Function is being retired - use diffUTCTime directly." #-}
 
 -- | Calculate the difference between two times in seconds.
@@ -115,12 +115,7 @@
 
 -- | A synonym for 'offsetTime'.
 offsetTimeIncrease :: IO (IO Seconds)
-offsetTimeIncrease = do
-    t <- offsetTime
-    ref <- newIORef 0
-    return $ do
-        t <- t
-        atomicModifyIORef ref $ \o -> let m = max t o in m `seq` (m, m)
+offsetTimeIncrease = offsetTime
 
 -- | Record how long a computation takes in 'Seconds'.
 --
diff --git a/test/TestGen.hs b/test/TestGen.hs
--- a/test/TestGen.hs
+++ b/test/TestGen.hs
@@ -53,8 +53,16 @@
     testGen "fromLeft 1 (Right \"foo\") == 1" $ fromLeft 1 (Right "foo") == 1
     testGen "fromRight 1 (Right 3) == 3" $ fromRight 1 (Right 3) == 3
     testGen "fromRight 1 (Left \"foo\") == 1" $ fromRight 1 (Left "foo") == 1
+    testGen "\\x -> fromLeft' (Left  x) == x" $ \x -> fromLeft' (Left  x) == x
+    testGen "\\x -> fromLeft' (Right x) == undefined" $ \x -> erroneous $ fromLeft' (Right x)
+    testGen "\\x -> fromRight' (Right x) == x" $ \x -> fromRight' (Right x) == x
+    testGen "\\x -> fromRight' (Left  x) == undefined" $ \x -> erroneous $ fromRight' (Left  x)
     testGen "\\x -> fromEither (Left x ) == x" $ \x -> fromEither (Left x ) == x
     testGen "\\x -> fromEither (Right x) == x" $ \x -> fromEither (Right x) == x
+    testGen "\\a b -> maybeToEither a (Just b) == Right b" $ \a b -> maybeToEither a (Just b) == Right b
+    testGen "\\a -> maybeToEither a Nothing == Left a" $ \a -> maybeToEither a Nothing == Left a
+    testGen "\\x -> eitherToMaybe (Left x) == Nothing" $ \x -> eitherToMaybe (Left x) == Nothing
+    testGen "\\x -> eitherToMaybe (Right x) == Just x" $ \x -> eitherToMaybe (Right x) == Just x
     testGen "\\xs -> repeatedly (splitAt 3) xs  == chunksOf 3 xs" $ \xs -> repeatedly (splitAt 3) xs  == chunksOf 3 xs
     testGen "\\xs -> repeatedly word1 (trim xs) == words xs" $ \xs -> repeatedly word1 (trim xs) == words xs
     testGen "\\xs -> repeatedly line1 xs == lines xs" $ \xs -> repeatedly line1 xs == lines xs
@@ -100,6 +108,9 @@
     testGen "splitAtEnd 3 \"he\"    == (\"\", \"he\")" $ splitAtEnd 3 "he"    == ("", "he")
     testGen "\\i xs -> uncurry (++) (splitAt i xs) == xs" $ \i xs -> uncurry (++) (splitAt i xs) == xs
     testGen "\\i xs -> splitAtEnd i xs == (dropEnd i xs, takeEnd i xs)" $ \i xs -> splitAtEnd i xs == (dropEnd i xs, takeEnd i xs)
+    testGen "\\i xs -> zip [i..] xs == zipFrom i xs" $ \i xs -> zip [i..] xs == zipFrom i xs
+    testGen "zipFrom False [1..3] == undefined" $ erroneous $ zipFrom False [1..3]
+    testGen "\\i xs -> zipWithFrom (,) i xs == zipFrom i xs" $ \i xs -> zipWithFrom (,) i xs == zipFrom i xs
     testGen "concatUnzip [(\"a\",\"AB\"),(\"bc\",\"C\")] == (\"abc\",\"ABC\")" $ concatUnzip [("a","AB"),("bc","C")] == ("abc","ABC")
     testGen "concatUnzip3 [(\"a\",\"AB\",\"\"),(\"bc\",\"C\",\"123\")] == (\"abc\",\"ABC\",\"123\")" $ concatUnzip3 [("a","AB",""),("bc","C","123")] == ("abc","ABC","123")
     testGen "takeWhileEnd even [2,3,4,6] == [4,6]" $ takeWhileEnd even [2,3,4,6] == [4,6]
diff --git a/test/TestUtil.hs b/test/TestUtil.hs
--- a/test/TestUtil.hs
+++ b/test/TestUtil.hs
@@ -47,11 +47,11 @@
     modifyIORef testCount (+1)
 
 
-erroneous :: a -> Bool
-erroneous x = unsafePerformIO $ fmap isLeft $ try_ $ evaluate x
+erroneous :: Show a => a -> Bool
+erroneous x = unsafePerformIO $ fmap isLeft $ try_ $ evaluate $ length $ show x
 
-erroneousIO :: IO a -> Bool
-erroneousIO x = unsafePerformIO $ fmap isLeft $ try_ $ evaluate =<< x
+erroneousIO :: Show a => IO a -> Bool
+erroneousIO x = unsafePerformIO $ fmap isLeft $ try_ $ evaluate . length . show =<< x
 
 (====) :: (Show a, Eq a) => a -> a -> Bool
 a ==== b = if a == b then True else error $ "Not equal!\n" ++ show a ++ "\n" ++ show b
