module Data.Lens.IxSet (ixLens) where import Data.IxSet import Data.Lens.Common import Data.Typeable -- |Focus on a key in an indexed set. -- -- Given an 'IxSet' of people: -- -- > people = fromList [ Person (FirstName "Edward A.") (LastName "Kmett") -- > , Person (FirstName "Simon") (LastName "P. Jones") -- > ] -- -- We can now work with indices as lenses and fix Simon's last name: -- -- > people' = lastName . ixLens (FirstName "Simon") ^= (LastName "Peyton-Jones") people -- -- Perhaps more commonly you're working with an IxSet from inside a state monad such as with acid-state. In that case usage is even easier: -- -- > changeLastName = lastName . ixLens (FirstName "Simon") %= LastName "Peyton-Jones" -- -- Feels backwards? Lens composition uses 'Category' so we can flip it -- around more intuitively using the composition arrows instead: -- -- > changeLastName' = ixLens (FirstName "Simon") >>> lastName %= LastName "Peyton-Jones" -- -- Here's the missing boilerplate: -- -- > {-# LANGUAGE DeriveDataTypeable #-} -- > {-# LANGUAGE TemplateHaskell #-} -- > -- > import Prelude hiding ((.)) -- > import Control.Category -- > import Data.Data -- > -- > import Data.Lens -- > import Data.Lens.Template -- > import Data.IxSet -- > -- > data Person = Person { _firstName :: FirstName -- > , _lastName :: LastName -- > } deriving (Show, Eq, Ord, Data, Typeable) -- > -- > mkLens ''Person -- > -- > newtype FirstName = FirstName String -- > deriving (Show, Eq, Ord, Data, Typeable) -- > -- > newtype LastName = LastName String -- > deriving (Show, Eq, Ord, Data, Typeable) -- > -- > instance Indexable Person where -- > empty = ixSet [ ixGen (Proxy :: Proxy FirstName) -- > , ixGen (Proxy :: Proxy LastName) -- > ] ixLens :: (Indexable a, Typeable a, Typeable k, Ord a) => k -> Lens (IxSet a) (Maybe a) ixLens k = lens get set where get = getOne . getEQ k set (Just v) = updateIx k v set Nothing = deleteIx k