content: {-|
  Module      : LensUtils
  Description : Lens utility functions
  Copyright   : (c) Eric Mertens, 2016
  License     : ISC
  Maintainer  : emertens@gmail.com
  
  This module provides functions that are useful with lenses.
  
  -}
  module LensUtils
    (
    -- * Strict update operations
      overStrict
    , setStrict
  
    -- * time lenses
    , zonedTimeLocalTime
    , localTimeTimeOfDay
    , localTimeDay
    ) where
  
  import Control.Lens (Lens', (??), set, ASetter, LensLike)
  import Data.Time (ZonedTime(ZonedTime), LocalTime(LocalTime), Day, TimeOfDay)
  import StrictUnit (StrictUnit(..))
  
  -- | Modify the target of a 'Setter' with a function. The result
  -- is strict in the results of applying the function. Strict version
  -- of 'over'
  overStrict :: LensLike ((,) StrictUnit) s t a b -> (a -> b) -> s -> t
  overStrict l f = run . l (nur . f)
    where
      nur y = (y `seq` StrictUnit, y)
      run (StrictUnit,y) = y
  {-# INLINE overStrict #-}
  
  -- | Set a value strictly in the set value. Strict version of 'set'.
  setStrict :: ASetter s t a b -> b -> s -> t
  setStrict l x = set l $! x
  {-# INLINE setStrict #-}
  
  -- | 'Lens' to the 'LocalTime' component of a 'ZonedTime'
  zonedTimeLocalTime :: Lens' ZonedTime LocalTime
  zonedTimeLocalTime f (ZonedTime t z) = (ZonedTime ?? z) <$> f t
  {-# INLINE zonedTimeLocalTime #-}
  
  -- | 'Lens' to the 'TimeOfDay component of a 'LocalTime'.
  localTimeTimeOfDay :: Lens' LocalTime TimeOfDay
  localTimeTimeOfDay f (LocalTime d t) = LocalTime d <$> f t
  {-# INLINE localTimeTimeOfDay #-}
  
  -- | 'Lens' to the 'TimeOfDay component of a 'LocalTime'.
  localTimeDay :: Lens' LocalTime Day
  localTimeDay f (LocalTime d t) = (LocalTime ?? t) <$> f d
  {-# INLINE localTimeDay #-}
  