{-# LANGUAGE FlexibleInstances, FunctionalDependencies, ScopedTypeVariables, IncoherentInstances, LambdaCase #-}

-- |Module `Containers.IsoMap` include type `IsoMap` and useful functions for
--  working with it.
--
--  `IsoMap` is kind of `Map` with isomorphism between keys and values. So,
--  difference between keys ans values is erased, and you can use as keys any
--  of two available sets, and other set will be used as values.
module Containers.IsoMap (
    IsoMap,
    size,
    empty,
    mapFst,
    mapSnd,
    mapFstRev,
    mapSndRev,
    module Containers.IsoMap.Iso,
  ) where

import Containers.IsoMap.Iso
import qualified Containers.Set as Set
import Containers.Map (Map)
import qualified Containers.Map as Map

import Data.Tuple (swap)
import Data.Function (on, (&))
import Data.Maybe (isNothing)
import Data.List.Extra (nubOrdBy)

newtype IsoMap a b = IsoMap { IsoMap a b -> (Map a b, Map b a)
mapsOf :: (Map a b, Map b a) }
    deriving (IsoMap a b -> IsoMap a b -> Bool
(IsoMap a b -> IsoMap a b -> Bool)
-> (IsoMap a b -> IsoMap a b -> Bool) -> Eq (IsoMap a b)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall a b. (Eq a, Eq b) => IsoMap a b -> IsoMap a b -> Bool
/= :: IsoMap a b -> IsoMap a b -> Bool
$c/= :: forall a b. (Eq a, Eq b) => IsoMap a b -> IsoMap a b -> Bool
== :: IsoMap a b -> IsoMap a b -> Bool
$c== :: forall a b. (Eq a, Eq b) => IsoMap a b -> IsoMap a b -> Bool
Eq)

instance (Show a, Show b) => Show (IsoMap a b) where
    show :: IsoMap a b -> String
show = Map a b -> String
forall a. Show a => a -> String
show (Map a b -> String)
-> (IsoMap a b -> Map a b) -> IsoMap a b -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map a b, Map b a) -> Map a b
forall a b. (a, b) -> a
fst ((Map a b, Map b a) -> Map a b)
-> (IsoMap a b -> (Map a b, Map b a)) -> IsoMap a b -> Map a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> (Map a b, Map b a)
forall a b. IsoMap a b -> (Map a b, Map b a)
mapsOf

uniqueValues :: Ord a => [a] -> Bool
uniqueValues :: [a] -> Bool
uniqueValues [a]
xs = Set a -> Int
forall a. Set a -> Int
Set.size ([a] -> Set a
forall a. Ord a => [a] -> Set a
Set.fromList [a]
xs) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [a]
xs

instance (Ord a, Ord b) => Iso (IsoMap a b) a b where
    ~& :: a -> IsoMap a b -> m b
(~&) a
a =
        m b -> (b -> m b) -> Maybe b -> m b
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> m b
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Can't find element in IsoMap") b -> m b
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe b -> m b) -> (IsoMap a b -> Maybe b) -> IsoMap a b -> m b
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
        a -> Map a b -> Maybe b
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup a
a (Map a b -> Maybe b)
-> (IsoMap a b -> Map a b) -> IsoMap a b -> Maybe b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map a b, Map b a) -> Map a b
forall a b. (a, b) -> a
fst ((Map a b, Map b a) -> Map a b)
-> (IsoMap a b -> (Map a b, Map b a)) -> IsoMap a b -> Map a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> (Map a b, Map b a)
forall a b. IsoMap a b -> (Map a b, Map b a)
mapsOf
    values :: IsoMap a b -> Set a
values = Map a b -> Set a
forall k a. Map k a -> Set k
Map.keysSet (Map a b -> Set a)
-> (IsoMap a b -> Map a b) -> IsoMap a b -> Set a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map a b, Map b a) -> Map a b
forall a b. (a, b) -> a
fst ((Map a b, Map b a) -> Map a b)
-> (IsoMap a b -> (Map a b, Map b a)) -> IsoMap a b -> Map a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> (Map a b, Map b a)
forall a b. IsoMap a b -> (Map a b, Map b a)
mapsOf
    member :: a -> IsoMap a b -> Bool
member a
a (IsoMap (Map a b
m, Map b a
_)) = a -> Map a b -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member a
a Map a b
m
    filter :: (a -> Bool) -> IsoMap a b -> IsoMap a b
filter a -> Bool
p (IsoMap (Map a b
m1, Map b a
m2)) =
        (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ((a -> b -> Bool) -> Map a b -> Map a b
forall k a. (k -> a -> Bool) -> Map k a -> Map k a
Map.filterWithKey (Bool -> b -> Bool
forall a b. a -> b -> a
const (Bool -> b -> Bool) -> (a -> Bool) -> a -> b -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Bool
p) Map a b
m1, (a -> Bool) -> Map b a -> Map b a
forall a k. (a -> Bool) -> Map k a -> Map k a
Map.filter a -> Bool
p Map b a
m2)
    insert :: (a, b) -> IsoMap a b -> m (IsoMap a b)
insert (a
a, b
b) (IsoMap (Map a b
m1, Map b a
m2)) =
        if Maybe b -> Bool
forall a. Maybe a -> Bool
isNothing (a -> Map a b -> Maybe b
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup a
a Map a b
m1) Bool -> Bool -> Bool
&& Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing (b -> Map b a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup b
b Map b a
m2)
        then IsoMap a b -> m (IsoMap a b)
forall (m :: * -> *) a. Monad m => a -> m a
return (IsoMap a b -> m (IsoMap a b)) -> IsoMap a b -> m (IsoMap a b)
forall a b. (a -> b) -> a -> b
$ (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap (a -> b -> Map a b -> Map a b
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert a
a b
b Map a b
m1, b -> a -> Map b a -> Map b a
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert b
b a
a Map b a
m2)
        else String -> m (IsoMap a b)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Can't insert element into IsoMap"
    delete :: a -> IsoMap a b -> IsoMap a b
delete a
a (IsoMap (Map a b
m, Map b a
_)) =
        let m' :: Map a b
m' = a -> Map a b -> Map a b
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete a
a Map a b
m
        in  (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap (Map a b
m', [(b, a)] -> Map b a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(b, a)] -> Map b a) -> [(b, a)] -> Map b a
forall a b. (a -> b) -> a -> b
$ ((a, b) -> (b, a)) -> [(a, b)] -> [(b, a)]
forall a b. (a -> b) -> [a] -> [b]
map (a, b) -> (b, a)
forall a b. (a, b) -> (b, a)
swap ([(a, b)] -> [(b, a)]) -> [(a, b)] -> [(b, a)]
forall a b. (a -> b) -> a -> b
$ Map a b -> [(a, b)]
forall k a. Map k a -> [(k, a)]
Map.toList Map a b
m')
    toMap :: IsoMap a b -> Map a b
toMap = (Map a b, Map b a) -> Map a b
forall a b. (a, b) -> a
fst ((Map a b, Map b a) -> Map a b)
-> (IsoMap a b -> (Map a b, Map b a)) -> IsoMap a b -> Map a b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> (Map a b, Map b a)
forall a b. IsoMap a b -> (Map a b, Map b a)
mapsOf
    fromList :: [(a, b)] -> m (IsoMap a b)
fromList [(a, b)]
ps =
        let ([a]
as, [b]
bs) = [(a, b)] -> ([a], [b])
forall a b. [(a, b)] -> ([a], [b])
unzip [(a, b)]
ps
        in
            if [a] -> Bool
forall a. Ord a => [a] -> Bool
uniqueValues [a]
as Bool -> Bool -> Bool
&& [b] -> Bool
forall a. Ord a => [a] -> Bool
uniqueValues [b]
bs
            then IsoMap a b -> m (IsoMap a b)
forall (m :: * -> *) a. Monad m => a -> m a
return (IsoMap a b -> m (IsoMap a b)) -> IsoMap a b -> m (IsoMap a b)
forall a b. (a -> b) -> a -> b
$ (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ([(a, b)] -> Map a b
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(a, b)]
ps, [(b, a)] -> Map b a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(b, a)] -> Map b a) -> [(b, a)] -> Map b a
forall a b. (a -> b) -> a -> b
$ ((a, b) -> (b, a)) -> [(a, b)] -> [(b, a)]
forall a b. (a -> b) -> [a] -> [b]
map (a, b) -> (b, a)
forall a b. (a, b) -> (b, a)
swap [(a, b)]
ps)
            else String -> m (IsoMap a b)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Can't create IsoMap from input list"
    fromList' :: [(a, b)] -> IsoMap a b
fromList' [(a, b)]
ps' =
        let ps :: [(a, b)]
ps = [(a, b)]
ps' [(a, b)] -> ([(a, b)] -> [(a, b)]) -> [(a, b)]
forall a b. a -> (a -> b) -> b
& ((a, b) -> (a, b) -> Ordering) -> [(a, b)] -> [(a, b)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
nubOrdBy (b -> b -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (b -> b -> Ordering)
-> ((a, b) -> b) -> (a, b) -> (a, b) -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (a, b) -> b
forall a b. (a, b) -> b
snd) ([(a, b)] -> [(a, b)])
-> ([(a, b)] -> [(a, b)]) -> [(a, b)] -> [(a, b)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((a, b) -> (a, b) -> Ordering) -> [(a, b)] -> [(a, b)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
nubOrdBy (a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (a -> a -> Ordering)
-> ((a, b) -> a) -> (a, b) -> (a, b) -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (a, b) -> a
forall a b. (a, b) -> a
fst)
        in  (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ([(a, b)] -> Map a b
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(a, b)]
ps, [(b, a)] -> Map b a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(b, a)] -> Map b a) -> [(b, a)] -> Map b a
forall a b. (a -> b) -> a -> b
$ ((a, b) -> (b, a)) -> [(a, b)] -> [(b, a)]
forall a b. (a -> b) -> [a] -> [b]
map (a, b) -> (b, a)
forall a b. (a, b) -> (b, a)
swap [(a, b)]
ps)
    toList :: IsoMap a b -> [(a, b)]
toList = Map a b -> [(a, b)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map a b -> [(a, b)])
-> (IsoMap a b -> Map a b) -> IsoMap a b -> [(a, b)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> Map a b
forall i a b. Iso i a b => i -> Map a b
toMap
    singleton :: a -> b -> IsoMap a b
singleton a
a b
b = (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap (a -> b -> Map a b
forall k a. k -> a -> Map k a
Map.singleton a
a b
b, b -> a -> Map b a
forall k a. k -> a -> Map k a
Map.singleton b
b a
a)

instance (Ord a, Ord b) => Iso (IsoMap a b) b a where
    ~& :: b -> IsoMap a b -> m a
(~&) b
b =
        m a -> (a -> m a) -> Maybe a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Can't find element in IsoMap") a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe a -> m a) -> (IsoMap a b -> Maybe a) -> IsoMap a b -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
        b -> Map b a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup b
b (Map b a -> Maybe a)
-> (IsoMap a b -> Map b a) -> IsoMap a b -> Maybe a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map a b, Map b a) -> Map b a
forall a b. (a, b) -> b
snd ((Map a b, Map b a) -> Map b a)
-> (IsoMap a b -> (Map a b, Map b a)) -> IsoMap a b -> Map b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> (Map a b, Map b a)
forall a b. IsoMap a b -> (Map a b, Map b a)
mapsOf
    values :: IsoMap a b -> Set b
values = Map b a -> Set b
forall k a. Map k a -> Set k
Map.keysSet (Map b a -> Set b)
-> (IsoMap a b -> Map b a) -> IsoMap a b -> Set b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Map a b, Map b a) -> Map b a
forall a b. (a, b) -> b
snd ((Map a b, Map b a) -> Map b a)
-> (IsoMap a b -> (Map a b, Map b a)) -> IsoMap a b -> Map b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> (Map a b, Map b a)
forall a b. IsoMap a b -> (Map a b, Map b a)
mapsOf
    member :: b -> IsoMap a b -> Bool
member b
b (IsoMap (Map a b
_, Map b a
m)) = b -> Map b a -> Bool
forall k a. Ord k => k -> Map k a -> Bool
Map.member b
b Map b a
m
    filter :: (b -> Bool) -> IsoMap a b -> IsoMap a b
filter b -> Bool
p (IsoMap (Map a b
m1, Map b a
m2)) =
        (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ((b -> Bool) -> Map a b -> Map a b
forall a k. (a -> Bool) -> Map k a -> Map k a
Map.filter b -> Bool
p Map a b
m1, (b -> a -> Bool) -> Map b a -> Map b a
forall k a. (k -> a -> Bool) -> Map k a -> Map k a
Map.filterWithKey (Bool -> a -> Bool
forall a b. a -> b -> a
const (Bool -> a -> Bool) -> (b -> Bool) -> b -> a -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. b -> Bool
p) Map b a
m2)
    insert :: (b, a) -> IsoMap a b -> m (IsoMap a b)
insert (b
b, a
a) (IsoMap (Map a b
m1, Map b a
m2)) =
        if Maybe b -> Bool
forall a. Maybe a -> Bool
isNothing (a -> Map a b -> Maybe b
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup a
a Map a b
m1) Bool -> Bool -> Bool
&& Maybe a -> Bool
forall a. Maybe a -> Bool
isNothing (b -> Map b a -> Maybe a
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup b
b Map b a
m2)
        then IsoMap a b -> m (IsoMap a b)
forall (m :: * -> *) a. Monad m => a -> m a
return (IsoMap a b -> m (IsoMap a b)) -> IsoMap a b -> m (IsoMap a b)
forall a b. (a -> b) -> a -> b
$ (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap (a -> b -> Map a b -> Map a b
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert a
a b
b Map a b
m1, b -> a -> Map b a -> Map b a
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert b
b a
a Map b a
m2)
        else String -> m (IsoMap a b)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Can't insert element into IsoMap"
    delete :: b -> IsoMap a b -> IsoMap a b
delete b
a (IsoMap (Map a b
_, Map b a
m)) =
        let m' :: Map b a
m' = b -> Map b a -> Map b a
forall k a. Ord k => k -> Map k a -> Map k a
Map.delete b
a Map b a
m
        in  (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ([(a, b)] -> Map a b
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(a, b)] -> Map a b) -> [(a, b)] -> Map a b
forall a b. (a -> b) -> a -> b
$ ((b, a) -> (a, b)) -> [(b, a)] -> [(a, b)]
forall a b. (a -> b) -> [a] -> [b]
map (b, a) -> (a, b)
forall a b. (a, b) -> (b, a)
swap ([(b, a)] -> [(a, b)]) -> [(b, a)] -> [(a, b)]
forall a b. (a -> b) -> a -> b
$ Map b a -> [(b, a)]
forall k a. Map k a -> [(k, a)]
Map.toList Map b a
m', Map b a
m')
    toMap :: IsoMap a b -> Map b a
toMap = (Map a b, Map b a) -> Map b a
forall a b. (a, b) -> b
snd ((Map a b, Map b a) -> Map b a)
-> (IsoMap a b -> (Map a b, Map b a)) -> IsoMap a b -> Map b a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> (Map a b, Map b a)
forall a b. IsoMap a b -> (Map a b, Map b a)
mapsOf
    fromList :: [(b, a)] -> m (IsoMap a b)
fromList [(b, a)]
ps =
        let ([b]
bs, [a]
as) = [(b, a)] -> ([b], [a])
forall a b. [(a, b)] -> ([a], [b])
unzip [(b, a)]
ps
        in
            if [a] -> Bool
forall a. Ord a => [a] -> Bool
uniqueValues [a]
as Bool -> Bool -> Bool
&& [b] -> Bool
forall a. Ord a => [a] -> Bool
uniqueValues [b]
bs
            then IsoMap a b -> m (IsoMap a b)
forall (m :: * -> *) a. Monad m => a -> m a
return (IsoMap a b -> m (IsoMap a b)) -> IsoMap a b -> m (IsoMap a b)
forall a b. (a -> b) -> a -> b
$ (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ([(a, b)] -> Map a b
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(a, b)] -> Map a b) -> [(a, b)] -> Map a b
forall a b. (a -> b) -> a -> b
$ ((b, a) -> (a, b)) -> [(b, a)] -> [(a, b)]
forall a b. (a -> b) -> [a] -> [b]
map (b, a) -> (a, b)
forall a b. (a, b) -> (b, a)
swap [(b, a)]
ps, [(b, a)] -> Map b a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(b, a)]
ps)
            else String -> m (IsoMap a b)
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Can't create IsoMap from input list"
    fromList' :: [(b, a)] -> IsoMap a b
fromList' [(b, a)]
ps' =
        let ps :: [(b, a)]
ps = [(b, a)]
ps' [(b, a)] -> ([(b, a)] -> [(b, a)]) -> [(b, a)]
forall a b. a -> (a -> b) -> b
& ((b, a) -> (b, a) -> Ordering) -> [(b, a)] -> [(b, a)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
nubOrdBy (b -> b -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (b -> b -> Ordering)
-> ((b, a) -> b) -> (b, a) -> (b, a) -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (b, a) -> b
forall a b. (a, b) -> a
fst) ([(b, a)] -> [(b, a)])
-> ([(b, a)] -> [(b, a)]) -> [(b, a)] -> [(b, a)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((b, a) -> (b, a) -> Ordering) -> [(b, a)] -> [(b, a)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
nubOrdBy (a -> a -> Ordering
forall a. Ord a => a -> a -> Ordering
compare (a -> a -> Ordering)
-> ((b, a) -> a) -> (b, a) -> (b, a) -> Ordering
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` (b, a) -> a
forall a b. (a, b) -> b
snd)
        in  (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ([(a, b)] -> Map a b
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList ([(a, b)] -> Map a b) -> [(a, b)] -> Map a b
forall a b. (a -> b) -> a -> b
$ ((b, a) -> (a, b)) -> [(b, a)] -> [(a, b)]
forall a b. (a -> b) -> [a] -> [b]
map (b, a) -> (a, b)
forall a b. (a, b) -> (b, a)
swap [(b, a)]
ps, [(b, a)] -> Map b a
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(b, a)]
ps)
    toList :: IsoMap a b -> [(b, a)]
toList = Map b a -> [(b, a)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map b a -> [(b, a)])
-> (IsoMap a b -> Map b a) -> IsoMap a b -> [(b, a)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. IsoMap a b -> Map b a
forall i a b. Iso i a b => i -> Map a b
toMap
    singleton :: b -> a -> IsoMap a b
singleton b
a a
b = (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap (a -> b -> Map a b
forall k a. k -> a -> Map k a
Map.singleton a
b b
a, b -> a -> Map b a
forall k a. k -> a -> Map k a
Map.singleton b
a a
b)

size :: IsoMap a b -> Int
size :: IsoMap a b -> Int
size (IsoMap (Map a b
m, Map b a
_)) = Map a b -> Int
forall k a. Map k a -> Int
Map.size Map a b
m

empty :: IsoMap a b
empty :: IsoMap a b
empty = (Map a b, Map b a) -> IsoMap a b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap (Map a b
forall k a. Map k a
Map.empty, Map b a
forall k a. Map k a
Map.empty)

mapFst :: Ord b => (a -> b) -> IsoMap a c -> IsoMap b c
mapFst :: (a -> b) -> IsoMap a c -> IsoMap b c
mapFst a -> b
f (IsoMap (Map a c
m1, Map c a
m2)) = (Map b c, Map c b) -> IsoMap b c
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ((a -> b) -> Map a c -> Map b c
forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeys a -> b
f Map a c
m1, (a -> b) -> Map c a -> Map c b
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map a -> b
f Map c a
m2)

mapSnd :: Ord b => (a -> b) -> IsoMap c a -> IsoMap c b
mapSnd :: (a -> b) -> IsoMap c a -> IsoMap c b
mapSnd a -> b
f (IsoMap (Map c a
m1, Map a c
m2)) = (Map c b, Map b c) -> IsoMap c b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ((a -> b) -> Map c a -> Map c b
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map a -> b
f Map c a
m1, (a -> b) -> Map a c -> Map b c
forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeys a -> b
f Map a c
m2)

mapFstRev :: Ord b => (a -> b) -> IsoMap a c -> IsoMap c b
mapFstRev :: (a -> b) -> IsoMap a c -> IsoMap c b
mapFstRev a -> b
f (IsoMap (Map a c
m1, Map c a
m2)) = (Map c b, Map b c) -> IsoMap c b
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ((a -> b) -> Map c a -> Map c b
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map a -> b
f Map c a
m2, (a -> b) -> Map a c -> Map b c
forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeys a -> b
f Map a c
m1)

mapSndRev :: Ord b => (a -> b) -> IsoMap c a -> IsoMap b c
mapSndRev :: (a -> b) -> IsoMap c a -> IsoMap b c
mapSndRev a -> b
f (IsoMap (Map c a
m1, Map a c
m2)) = (Map b c, Map c b) -> IsoMap b c
forall a b. (Map a b, Map b a) -> IsoMap a b
IsoMap ((a -> b) -> Map a c -> Map b c
forall k2 k1 a. Ord k2 => (k1 -> k2) -> Map k1 a -> Map k2 a
Map.mapKeys a -> b
f Map a c
m2, (a -> b) -> Map c a -> Map c b
forall a b k. (a -> b) -> Map k a -> Map k b
Map.map a -> b
f Map c a
m1)