{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE FlexibleContexts #-}

{-| 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.
 
To derive automatically 'Simplifiable', add language extensions 'DeriveAnyClass' and 'DeriveGeneric', import  'GHC.Generics' and add 'Generic' and 'Simplifiable' to the derived typeclasses of your datatype. (For example : "data Foo a = Foo (Set a) deriving (Generic, Simplifiable)".)

-}

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                  Data.Int
    import                  Data.Word
    import                  GHC.Generics
    
    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
        
        default simplify :: (Generic a, GSimplifiable (Rep a)) => a -> a
        simplify a
a = Rep a Any -> a
forall a x. Generic a => Rep a x -> a
forall x. Rep a x -> a
to (Rep a Any -> a) -> Rep a Any -> a
forall a b. (a -> b) -> a -> b
$ Rep a Any -> Rep a Any
forall a. Rep a a -> Rep a a
forall (f :: * -> *) a. GSimplifiable f => f a -> f a
gsimplify (a -> Rep a Any
forall x. a -> Rep a x
forall a x. Generic a => a -> Rep a x
from a
a)
        
    class GSimplifiable f where
        gsimplify :: f a -> f a
        
    instance GSimplifiable U1 where
        gsimplify :: forall a. U1 a -> U1 a
gsimplify U1 a
U1 = U1 a
forall k (p :: k). U1 p
U1
        
    instance (GSimplifiable a, GSimplifiable b) => GSimplifiable (a :*: b) where
        gsimplify :: forall a. (:*:) a b a -> (:*:) a b a
gsimplify (a a
a :*: b a
b) = (a a -> a a
forall a. a a -> a a
forall (f :: * -> *) a. GSimplifiable f => f a -> f a
gsimplify a a
a) a a -> b a -> (:*:) a b a
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: (b a -> b a
forall a. b a -> b a
forall (f :: * -> *) a. GSimplifiable f => f a -> f a
gsimplify b a
b) 
         
    instance (GSimplifiable a, GSimplifiable b) => GSimplifiable (a :+: b) where
        gsimplify :: forall a. (:+:) a b a -> (:+:) a b a
gsimplify (L1 a a
a) = a a -> (:+:) a b a
forall k (f :: k -> *) (g :: k -> *) (p :: k). f p -> (:+:) f g p
L1 (a a -> (:+:) a b a) -> a a -> (:+:) a b a
forall a b. (a -> b) -> a -> b
$ a a -> a a
forall a. a a -> a a
forall (f :: * -> *) a. GSimplifiable f => f a -> f a
gsimplify a a
a
        gsimplify (R1 b a
b) = b a -> (:+:) a b a
forall k (f :: k -> *) (g :: k -> *) (p :: k). g p -> (:+:) f g p
R1 (b a -> (:+:) a b a) -> b a -> (:+:) a b a
forall a b. (a -> b) -> a -> b
$ b a -> b a
forall a. b a -> b a
forall (f :: * -> *) a. GSimplifiable f => f a -> f a
gsimplify b a
b
        
        
    instance (GSimplifiable a) => GSimplifiable (M1 i c a) where
        gsimplify :: forall a. M1 i c a a -> M1 i c a a
gsimplify (M1 a a
a) = a a -> M1 i c a a
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 (a a -> M1 i c a a) -> a a -> M1 i c a a
forall a b. (a -> b) -> a -> b
$ a a -> a a
forall a. a a -> a a
forall (f :: * -> *) a. GSimplifiable f => f a -> f a
gsimplify a a
a

    instance (Simplifiable a) => GSimplifiable (K1 i a) where
        gsimplify :: forall a. K1 i a a -> K1 i a a
gsimplify (K1 a
x) = a -> K1 i a a
forall k i c (p :: k). c -> K1 i c p
K1 (a -> K1 i a a) -> a -> K1 i a a
forall a b. (a -> b) -> a -> b
$ a -> a
forall a. Simplifiable a => a -> a
simplify a
x
       
        
        
        
        
        
        
    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 Double where
        simplify :: Double -> Double
simplify = Double -> Double
forall a. a -> a
id

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

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

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

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

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

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

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

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

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

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

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

    instance Simplifiable () where
        simplify :: () -> ()
simplify = () -> ()
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