packages feed

equivalence 0.4.0.1 → 0.4.1

raw patch · 5 files changed

+128/−36 lines, 5 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ Data.Equivalence.Monad: classes :: (MonadEquiv c v d m, MonadEquiv c v d n, MonadTrans t, t n ~ m) => m [c]
+ Data.Equivalence.Monad: values :: (MonadEquiv c v d m, MonadEquiv c v d n, MonadTrans t, t n ~ m) => m [v]
+ Data.Equivalence.STT: classes :: (Monad m, Applicative m, Ord a) => Equiv s c a -> STT s m [Class s c a]
+ Data.Equivalence.STT: values :: (Monad m, Applicative m, Ord a) => Equiv s c a -> STT s m [a]

Files

CHANGES.md view
@@ -1,3 +1,15 @@+0.4.1+-----++_Andreas Abel, 2022-07-26_++* New methods `values` and `classes` to get all values and classes encountered+  [#7](https://github.com/pa-ba/equivalence/issues/7)+  [#13](https://github.com/pa-ba/equivalence/pull/13)+  (contributed by Jimmy Koppel).++Tested with GHC 7.10 - 9.4.1 RC1.+ 0.4.0.1 ------- @@ -10,7 +22,7 @@  _Andreas Abel, 2022-02-03_ -* remove ErrorT instance for compatibility with transformers-0.6 and mtl-2.3+* remove `ErrorT` instance for compatibility with `transformers-0.6` and `mtl-2.3`  0.3.5 -----@@ -21,7 +33,7 @@  0.3.4 ------* MonadFail instance for EquivT+* `MonadFail` instance for `EquivT`  0.3.3 -----@@ -29,16 +41,16 @@  0.3.2 ------* add Applicative constraints for backwards compatibility with GHC 7.8+* add `Applicative` constraints for backwards compatibility with GHC 7.8  0.3.1 ------* use transformers-compat for backwards compatibility with older versions of transformers+* use `transformers-compat` for backwards compatibility with older versions of `transformers`  0.3.0.1 --------* add CHANGES.txt to .cabal file+* add `CHANGES.txt` to `.cabal` file  0.3 ----* add suport for Control.Monad.Except (thus the new dependency constraint 'mtl >= 2.2.1')+* add suport for `Control.Monad.Except` (thus the new dependency constraint `mtl >= 2.2.1`)
equivalence.cabal view
@@ -1,10 +1,10 @@ Cabal-Version:   >= 1.10 Name:            equivalence-Version:         0.4.0.1+Version:         0.4.1 License:         BSD3 License-File:    LICENSE Author:          Patrick Bahr-Maintainer:      paba@itu.dk+Maintainer:      Andreas Abel Homepage:        https://github.com/pa-ba/equivalence bug-reports:     https://github.com/pa-ba/equivalence/issues Synopsis:        Maintaining an equivalence relation implemented as union-find using STT.@@ -22,7 +22,7 @@  tested-with:   GHC == 9.4.1-  GHC == 9.2.2+  GHC == 9.2.3   GHC == 9.0.2   GHC == 8.10.7   GHC == 8.8.4
src/Data/Equivalence/Monad.hs view
@@ -39,7 +39,8 @@      ) where  import Data.Equivalence.STT hiding (equate, equateAll, equivalent, classDesc, removeClass,-                                    getClass , combine, combineAll, same , desc , remove )+                                    getClass , combine, combineAll, same , desc , remove,+                                    values , classes ) import qualified Data.Equivalence.STT  as S  @@ -204,6 +205,20 @@      remove :: c -> m Bool +    {-| This function returns all values represented by+       some equivalence class.++       @since 0.4.1 -}++    values :: m [v]++    {-| This function returns the list of+       all equivalence classes.++       @since 0.4.1 -}++    classes :: m [c]+     -- Default implementations for lifting via a monad transformer.     -- Unfortunately, GHC does not permit us to give these also to     -- 'equate' and 'combine', which already have a default implementation.@@ -235,7 +250,13 @@     default remove      :: (MonadEquiv c v d n, MonadTrans t, t n ~ m) => c -> m Bool     remove               = lift . remove +    default values      :: (MonadEquiv c v d n, MonadTrans t, t n ~ m) => m [v]+    values               = lift values +    default classes     :: (MonadEquiv c v d n, MonadTrans t, t n ~ m) => m [c]+    classes              = lift classes++ instance (Monad m, Applicative m, Ord v) => MonadEquiv (Class s d v) v d (EquivT s d v m) where     equivalent x y = EquivT $ do       part <- ask@@ -281,6 +302,14 @@       part <- ask       lift $ S.remove part x +    values = EquivT $ do+      part <- ask+      lift $ S.values part++    classes = EquivT $ do+      part <- ask+      lift $ S.classes part+ instance (MonadEquiv c v d m, Monoid w) => MonadEquiv c v d (WriterT w m) where     equate  x y = lift $ equate x y     combine x y = lift $ combine x y@@ -288,6 +317,7 @@ instance (MonadEquiv c v d m) => MonadEquiv c v d (ExceptT e m) where     equate  x y = lift $ equate x y     combine x y = lift $ combine x y+  instance (MonadEquiv c v d m) => MonadEquiv c v d (StateT s m) where     equate  x y = lift $ equate x y
src/Data/Equivalence/STT.hs view
@@ -57,6 +57,9 @@   , equivalent   , classDesc   , removeClass+  -- Getting all represented items+  , values+  , classes   ) where  import Control.Monad.ST.Trans@@ -405,3 +408,24 @@         then return False         else removeEntry (fromMaybe entry mentry)              >> return True++{-| This function returns all values represented by+   some equivalence class. -}++values :: (Monad m, Applicative m, Ord a) => Equiv s c a -> STT s m [a]+values Equiv {entries = mref} = Map.keys <$> readSTRef mref++{-| This function returns the list of+   all equivalence classes. -}++classes :: (Monad m, Applicative m, Ord a) => Equiv s c a -> STT s m [Class s c a]+classes Equiv {entries = mref} = do+  allEntries <- Map.elems <$> readSTRef mref+  rootEntries <- filterM isRoot allEntries+  mapM (fmap Class . newSTRef) $ rootEntries+    where+      isRoot e = do+        x <- readSTRef (unentry e)+        case x of+          Node {} -> return False+          Root {} -> return True
testsuite/tests/Data/Equivalence/Monad_Test.hs view
@@ -1,24 +1,23 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes, TemplateHaskell #-}+{-# LANGUAGE ScopedTypeVariables #-}  module Data.Equivalence.Monad_Test where -import Test.QuickCheck hiding ((===))+import Test.QuickCheck hiding ((===), classes)  import Data.Equivalence.Monad  import Control.Monad+import Data.Function (on) import Data.Set (Set) import qualified Data.Set as Set import System.Exit -- -------------------------------------------------------------------------------- -- Test Suits -------------------------------------------------------------------------------- - -- run :: (Ord a) => STT s Identity (Equiv s (Set a) a) run :: (Ord v) => (forall s. EquivM s (Set v) v a) -> a run = runEquivM Set.singleton Set.union@@ -30,7 +29,13 @@  getClasses l1 = mapM getClass l1 +infixr 9 <.> +-- | Composition: pure function after functorial (monadic) function.+(<.>) :: Functor m => (b -> c) -> (a -> m b) -> a -> m c+(f <.> g) a = f <$> g a++ -------------------------------------------------------------------------------- -- Properties --------------------------------------------------------------------------------@@ -43,7 +48,7 @@   let l = v:l'   equateAll l   d <- classDesc v-  return  (d == Set.fromList l)+  return (d == Set.fromList l)  prop_combineAll l' v = runInt $ do   let l = v:l'@@ -134,28 +139,49 @@   return (Set.fromList l2 == d)  -prop_classes l1 l1' l2 x y = putStrLn (show el ++ ";" ++ show cl) `whenFail` (el == cl)-    where l3 = concat (l2 : l1)-          el = runInt $ do-                 mapM equateAll l1-                 mapM removeClass l2-                 mapM equateAll (l1' :: [[Int]])-                 res <- mapM classDesc l3-                 eq <- equivalent x y-                 return (res,eq)-          cl = runInt $ do-                 cls1 <- mapM getClasses l1-                 mapM combineAll cls1-                 cls2 <- getClasses l2-                 mapM remove cls2-                 cls1' <- mapM getClasses l1'-                 mapM combineAll cls1'-                 cls3 <- getClasses l3-                 res <- mapM desc cls3-                 [cx,cy] <- getClasses [x,y]-                 eq <- cx === cy-                 return (res,eq)+prop_getClasses l1 l1' l2 x y =+  putStrLn (show el ++ ";" ++ show cl) `whenFail` (el == cl)+  where+    l3 = concat (l2 : l1) +    el = runInt $ do+      mapM equateAll l1+      mapM removeClass l2+      mapM equateAll (l1' :: [[Int]])+      res <- mapM classDesc l3+      eq <- equivalent x y+      return (res,eq)++    cl = runInt $ do+      cls1 <- mapM getClasses l1+      mapM combineAll cls1+      cls2 <- getClasses l2+      mapM remove cls2+      cls1' <- mapM getClasses l1'+      mapM combineAll cls1'+      cls3 <- getClasses l3+      res <- mapM desc cls3+      [cx,cy] <- getClasses [x,y]+      eq <- cx === cy+      return (res,eq)++prop_values l = runInt $ do+    mapM (\x -> equate x x) l+    sameSet l <$> values+  where+    sameSet = (==) `on` Set.fromList++prop_classes l = runInt $ do+    mapM equateAll (l :: [[Int]])+    classes1 <- uniqClass =<< mapM getClass =<< values+    sameClasses classes1 =<< classes+  where+    uniqClass []     = return []+    uniqClass (c:cs) = (c :) <$> do+      uniqClass =<< filterM (not <.> (c ===)) cs++    sameClasses []       cs2 = return $ null cs2+    sameClasses (c:cs1') cs2 = sameClasses cs1' =<< filterM (not <.> (c ===)) cs2  return []