Commit f6c6c63b authored by Petr Pudlak's avatar Petr Pudlak

Add a lens for Set that works with 'Bool -> Bool'

This allow to work with sets using the standard lens mechanisms.

Also add a function that creates a lens where a setter function also
uses the information from a getter. This allows to optimize the setter,
in particular in the case of Set, keep the set unmodified, if the inner
function doesn't change anything.
Signed-off-by: default avatarPetr Pudlak <>
Reviewed-by: default avatarKlaus Aehlig <>
parent f645af36
{-# LANGUAGE RankNTypes #-}
{-| Provides all lens-related functions.
......@@ -25,17 +27,25 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
module Ganeti.Lens
( module Control.Lens
, lensWith
, makeCustomLenses
, makeCustomLenses'
, traverseOf2
, atSet
) where
import Control.Applicative ((<$>))
import Control.Lens
import Control.Monad
import Data.Functor.Compose (Compose(..))
import qualified Data.Set as S
import Language.Haskell.TH
-- | Creates an optimized lens where the setter also gets the original value
-- from the getter.
lensWith :: (s -> a) -> (s -> a -> b -> t) -> Lens s t a b
lensWith sa sbt f s = uncurry (sbt s) <$> (\a -> fmap ((,) a) (f a)) (sa s)
lensFieldName :: String -> String
lensFieldName = (++ "L")
......@@ -65,3 +75,14 @@ makeCustomLenses' name lst = makeCustomLensesFiltered f name
traverseOf2 :: Over (->) (Compose f g) s t a b
-> (a -> f (g b)) -> s -> f (g t)
traverseOf2 k f = getCompose . traverseOf k (Compose . f)
-- | A helper lens over sets.
-- While a similar lens exists in the package (as @Lens' Set (Maybe ())@@),
-- it's available only in most recent versions.
-- And using @Bool@ instead of @Maybe ()@ is more convenient.
atSet :: (Ord a) => a -> Lens' (S.Set a) Bool
atSet k = lensWith (S.member k) f
f s True False = S.delete k s
f s False True = S.insert k s
f s _ _ = s
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment