{- |
This module allows to access elements of arrays, sets and finite maps
like elements of records.
This is especially useful for working with nested structures
consisting of arrays, sets, maps and records.

Maybe we should move it to a separate package,
then we would not need to import @array@ and @containers@ package.
-}
module Data.Accessor.Container
   (array, set,
    mapDefault, mapMaybe,
    intMapDefault, intMapMaybe,
   ) where

import qualified Data.Accessor.Basic as Accessor

import Data.Ix (Ix, )
import qualified Data.Array  as Array
import qualified Data.Set    as Set
import qualified Data.Map    as Map
import qualified Data.IntMap as IntMap

import Prelude hiding (map)


array :: Ix i => i -> Accessor.T (Array.Array i e) e
array :: forall i e. Ix i => i -> T (Array i e) e
array i
i = (e -> Array i e -> Array i e)
-> (Array i e -> e) -> T (Array i e) e
forall a r. (a -> r -> r) -> (r -> a) -> T r a
Accessor.fromSetGet (\e
e Array i e
a -> Array i e
a Array i e -> [(i, e)] -> Array i e
forall i e. Ix i => Array i e -> [(i, e)] -> Array i e
Array.// [(i
i,e
e)]) (Array i e -> i -> e
forall i e. Ix i => Array i e -> i -> e
Array.! i
i)

{- |
Treat a Set like a boolean array.
-}
set :: Ord a => a -> Accessor.T (Set.Set a) Bool
set :: forall a. Ord a => a -> T (Set a) Bool
set a
a =
   (Bool -> Set a -> Set a) -> (Set a -> Bool) -> T (Set a) Bool
forall a r. (a -> r -> r) -> (r -> a) -> T r a
Accessor.fromSetGet
      (\Bool
b -> if Bool
b then a -> Set a -> Set a
forall a. Ord a => a -> Set a -> Set a
Set.insert a
a else a -> Set a -> Set a
forall a. Ord a => a -> Set a -> Set a
Set.delete a
a)
      (a -> Set a -> Bool
forall a. Ord a => a -> Set a -> Bool
Set.member a
a)

{- |
Treats a finite map like an infinite map,
where all undefined elements are replaced by a default value.
-}
mapDefault :: Ord key => elem -> key -> Accessor.T (Map.Map key elem) elem
mapDefault :: forall key elem. Ord key => elem -> key -> T (Map key elem) elem
mapDefault elem
deflt key
key =
   (elem -> Map key elem -> Map key elem)
-> (Map key elem -> elem) -> T (Map key elem) elem
forall a r. (a -> r -> r) -> (r -> a) -> T r a
Accessor.fromSetGet (key -> elem -> Map key elem -> Map key elem
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert key
key) (elem -> key -> Map key elem -> elem
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault elem
deflt key
key)

{- |
Treats a finite map like an infinite map,
where all undefined elements are 'Nothing'
and defined elements are 'Just'.
-}
mapMaybe :: Ord key => key -> Accessor.T (Map.Map key elem) (Maybe elem)
mapMaybe :: forall key elem. Ord key => key -> T (Map key elem) (Maybe elem)
mapMaybe key
key =
   (Maybe elem -> Map key elem -> Map key elem)
-> (Map key elem -> Maybe elem) -> T (Map key elem) (Maybe elem)
forall a r. (a -> r -> r) -> (r -> a) -> T r a
Accessor.fromSetGet
      (\Maybe elem
e Map key elem
m -> Map key elem
-> (elem -> Map key elem) -> Maybe elem -> Map key elem
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (key -> Map key elem -> Map key elem
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete key
key Map key elem
m) ((elem -> Map key elem -> Map key elem)
-> Map key elem -> elem -> Map key elem
forall a b c. (a -> b -> c) -> b -> a -> c
flip (key -> elem -> Map key elem -> Map key elem
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert key
key) Map key elem
m) Maybe elem
e)
      (key -> Map key elem -> Maybe elem
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup key
key)

intMapDefault :: elem -> Int -> Accessor.T (IntMap.IntMap elem) elem
intMapDefault :: forall elem. elem -> Int -> T (IntMap elem) elem
intMapDefault elem
deflt Int
key =
   (elem -> IntMap elem -> IntMap elem)
-> (IntMap elem -> elem) -> T (IntMap elem) elem
forall a r. (a -> r -> r) -> (r -> a) -> T r a
Accessor.fromSetGet (Int -> elem -> IntMap elem -> IntMap elem
forall a. Int -> a -> IntMap a -> IntMap a
IntMap.insert Int
key) (elem -> Int -> IntMap elem -> elem
forall a. a -> Int -> IntMap a -> a
IntMap.findWithDefault elem
deflt Int
key)

intMapMaybe :: Int -> Accessor.T (IntMap.IntMap elem) (Maybe elem)
intMapMaybe :: forall elem. Int -> T (IntMap elem) (Maybe elem)
intMapMaybe Int
key =
   (Maybe elem -> IntMap elem -> IntMap elem)
-> (IntMap elem -> Maybe elem) -> T (IntMap elem) (Maybe elem)
forall a r. (a -> r -> r) -> (r -> a) -> T r a
Accessor.fromSetGet
      (\Maybe elem
e IntMap elem
m -> IntMap elem -> (elem -> IntMap elem) -> Maybe elem -> IntMap elem
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Int -> IntMap elem -> IntMap elem
forall a. Int -> IntMap a -> IntMap a
IntMap.delete Int
key IntMap elem
m) ((elem -> IntMap elem -> IntMap elem)
-> IntMap elem -> elem -> IntMap elem
forall a b c. (a -> b -> c) -> b -> a -> c
flip (Int -> elem -> IntMap elem -> IntMap elem
forall a. Int -> a -> IntMap a -> IntMap a
IntMap.insert Int
key) IntMap elem
m) Maybe elem
e)
      (Int -> IntMap elem -> Maybe elem
forall a. Int -> IntMap a -> Maybe a
IntMap.lookup Int
key)