{-| Module  : WeakSets
Description : A container may be simplified internally by the call of a function 'simplify'. This is the case for 'WeakSet's
 and 'WeakMap's where duplicate elements remain in the container until the end of the lifetime of the container. Calling 'simplify' on them will remove duplicate elements.
Copyright   : Guillaume Sabbagh 2022
License     : LGPL-3.0-or-later
Maintainer  : guillaumesabbagh@protonmail.com
Stability   : experimental
Portability : portable

A container may be simplified internally by the call of a function 'simplify'. This is the case for 'WeakSet's
 and 'WeakMap's where duplicate elements remain in the container until the end of the lifetime of the container. Calling 'simplify' on them will remove duplicate elements.

-}

module Data.Simplifiable
(
    Simplifiable(..),
)
where

    import qualified        Data.WeakSet        as Set
    import qualified        Data.WeakMap        as Map
    import                  Data.WeakMap.Safe
    import qualified        Data.List           as List
    
    import                  Numeric.Natural


    -- | A container may be simplified internally by the call of a function 'simplify'. This is the case for 'WeakSet's

    -- and 'WeakMap's where duplicate elements remain in the container until the end of the lifetime of the container. Calling --'simplify' on them will remove duplicate elements.

    class Simplifiable a where
        -- | A function to simplify a container recursively.

        simplify :: a -> a
        
    instance Simplifiable Bool where
        simplify :: Bool -> Bool
simplify = Bool -> Bool
forall a. a -> a
id

    instance Simplifiable Char where
        simplify :: Char -> Char
simplify = Char -> Char
forall a. a -> a
id

    instance Simplifiable Int where
        simplify :: Int -> Int
simplify = Int -> Int
forall a. a -> a
id

    instance Simplifiable Natural where
        simplify :: Natural -> Natural
simplify = Natural -> Natural
forall a. a -> a
id

    instance Simplifiable Float where
        simplify :: Float -> Float
simplify = Float -> Float
forall a. a -> a
id

    instance Simplifiable Double where
        simplify :: Double -> Double
simplify = Double -> Double
forall a. a -> a
id
        
    instance (Simplifiable a, Simplifiable b) => Simplifiable (a,b) where
        simplify :: (a, b) -> (a, b)
simplify (a
a,b
b) = (a -> a
forall a. Simplifiable a => a -> a
simplify a
a, b -> b
forall a. Simplifiable a => a -> a
simplify b
b)
        
    instance (Simplifiable a, Simplifiable b, Simplifiable c) => Simplifiable (a,b,c) where
        simplify :: (a, b, c) -> (a, b, c)
simplify (a
a,b
b,c
c) = (a -> a
forall a. Simplifiable a => a -> a
simplify a
a, b -> b
forall a. Simplifiable a => a -> a
simplify b
b, c -> c
forall a. Simplifiable a => a -> a
simplify c
c)
        
    instance (Simplifiable a, Simplifiable b, Simplifiable c, Simplifiable d) => Simplifiable (a,b,c,d) where
        simplify :: (a, b, c, d) -> (a, b, c, d)
simplify (a
a,b
b,c
c,d
d) = (a -> a
forall a. Simplifiable a => a -> a
simplify a
a, b -> b
forall a. Simplifiable a => a -> a
simplify b
b, c -> c
forall a. Simplifiable a => a -> a
simplify c
c, d -> d
forall a. Simplifiable a => a -> a
simplify d
d)
        
    instance (Simplifiable a, Simplifiable b, Simplifiable c, Simplifiable d, Simplifiable e) => Simplifiable (a,b,c,d,e) where
        simplify :: (a, b, c, d, e) -> (a, b, c, d, e)
simplify (a
a,b
b,c
c,d
d,e
e) = (a -> a
forall a. Simplifiable a => a -> a
simplify a
a, b -> b
forall a. Simplifiable a => a -> a
simplify b
b, c -> c
forall a. Simplifiable a => a -> a
simplify c
c, d -> d
forall a. Simplifiable a => a -> a
simplify d
d, e -> e
forall a. Simplifiable a => a -> a
simplify e
e)
        
    instance (Simplifiable a, Eq a) => Simplifiable (Set.Set a) where
        simplify :: Set a -> Set a
simplify Set a
s = [a] -> Set a
forall a. [a] -> Set a
Set.set ([a] -> Set a) -> [a] -> Set a
forall a b. (a -> b) -> a -> b
$ Set a -> [a]
forall a. Eq a => Set a -> [a]
Set.setToList (Set a -> [a]) -> Set a -> [a]
forall a b. (a -> b) -> a -> b
$ a -> a
forall a. Simplifiable a => a -> a
simplify (a -> a) -> Set a -> Set a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Set a
s
        
    instance (Simplifiable k, Simplifiable v, Eq k) => Simplifiable (Map.Map k v) where
        simplify :: Map k v -> Map k v
simplify Map k v
m = AssociationList k v -> Map k v
forall k v. AssociationList k v -> Map k v
Map.weakMap (AssociationList k v -> Map k v) -> AssociationList k v -> Map k v
forall a b. (a -> b) -> a -> b
$ Map k v -> AssociationList k v
forall k v. Eq k => Map k v -> AssociationList k v
Map.mapToList (Map k v -> AssociationList k v) -> Map k v -> AssociationList k v
forall a b. (a -> b) -> a -> b
$ (k, v) -> (k, v)
forall a. Simplifiable a => a -> a
simplify ((k, v) -> (k, v)) -> Map k v -> Map k v
forall k1 v1 k2 v2.
((k1, v1) -> (k2, v2)) -> Map k1 v1 -> Map k2 v2
<|$|> Map k v
m

    instance (Simplifiable a) => Simplifiable [a] where
        simplify :: [a] -> [a]
simplify [a]
xs = a -> a
forall a. Simplifiable a => a -> a
simplify (a -> a) -> [a] -> [a]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [a]
xs
        
    instance (Simplifiable a) => Simplifiable (Maybe a) where
        simplify :: Maybe a -> Maybe a
simplify Maybe a
x = a -> a
forall a. Simplifiable a => a -> a
simplify (a -> a) -> Maybe a -> Maybe a
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
x
        
    instance (Simplifiable a, Simplifiable b) => Simplifiable (Either a b) where
        simplify :: Either a b -> Either a b
simplify (Left a
a) = a -> Either a b
forall a b. a -> Either a b
Left (a -> Either a b) -> a -> Either a b
forall a b. (a -> b) -> a -> b
$ a -> a
forall a. Simplifiable a => a -> a
simplify a
a
        simplify (Right b
a) = b -> Either a b
forall a b. b -> Either a b
Right (b -> Either a b) -> b -> Either a b
forall a b. (a -> b) -> a -> b
$ b -> b
forall a. Simplifiable a => a -> a
simplify b
a