Skip to content

Commit

Permalink
[#35] Integration with containers (#52)
Browse files Browse the repository at this point in the history
* [#35] Integration with `containers`

Resolves #35

* Fix containers lower bound for GHC-8.2
  • Loading branch information
vrom911 authored Mar 18, 2021
1 parent bfde7cd commit bf84c7d
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 2 deletions.
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ The changelog is available [on GitHub][2].
* [#36](https://github.com/kowainik/slist/issues/36):
Add strict functions: `append'`, `concat'` and `concatMap'`.
* [#30](https://github.com/kowainik/slist/issues/30):
Add the `cons` function.
Add `cons` and `cons'` functions.
* [#35](https://github.com/kowainik/slist/issues/35):
Add integration with the `containers` library: `mapToKeys`, `mapToVals`,
`mapToPairs`, `setToSlist`.

Add `ordNub`.
* [#34](https://github.com/kowainik/slist/issues/34):
Add `partitionWith` and `listPartitionWith`.
* [#29](https://github.com/kowainik/slist/issues/29):
Expand Down
2 changes: 2 additions & 0 deletions slist.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ common common-options

library
import: common-options
build-depends: containers >= 0.5 && <= 0.7
hs-source-dirs: src
exposed-modules: Slist
Slist.Containers
Slist.Maybe
Slist.Size
Slist.Type
Expand Down
36 changes: 36 additions & 0 deletions src/Slist.hs
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ module Slist
-- $sets
, nub
, nubBy
, ordNub
, delete
, deleteBy
, deleteFirstsBy
Expand Down Expand Up @@ -223,6 +224,16 @@ module Slist
, catMaybes
, mapMaybe
, slistWith

-- * Containers
-- ** Map
, mapToVals
, mapToKeys
, mapToPairs

-- ** Set
, setToSlist

) where

import Data.Bifunctor (bimap, first, second)
Expand All @@ -237,11 +248,13 @@ import Prelude hiding (break, concat, concatMap, cycle, drop, dropWhile, filter,
scanr1, span, splitAt, tail, take, takeWhile, unzip, unzip3, zip, zip3, zipWith,
zipWith3)

import Slist.Containers (mapToKeys, mapToPairs, mapToVals, setToSlist)
import Slist.Maybe (catMaybes, mapMaybe, maybeToSlist, slistToMaybe, slistWith)
import Slist.Size (Size (..), sizes)
import Slist.Type (Slist (..), cons, infiniteSlist, isEmpty, len, map, one, size, slist)

import qualified Data.List as L
import qualified Data.Set as Set
import qualified GHC.Exts as Exts
import qualified Prelude as P

Expand Down Expand Up @@ -1668,6 +1681,29 @@ nubBy f Slist{..} = let (s, l) = go 0 [] sList in case sSize of
else go (n + 1) (res ++ [x]) xs
{-# INLINE nubBy #-}

{- | Removes duplicate elements from a slist, keeping only the first occurance of
the element.
Like 'nub' but runs in \( O(n \log n) \) time and requires 'Ord'.
>>> ordNub $ slist [3, 3, 3, 2, 2, -1, 1]
Slist {sList = [3,2,-1,1], sSize = Size 4}
-}
ordNub :: forall a . (Ord a) => Slist a -> Slist a
ordNub sl = let (s, l) = go 0 Set.empty (sList sl) in Slist
{ sList = l
, sSize = Size s
}
where
go :: Int -> Set.Set a -> [a] -> (Int, [a])
go !i _ [] = (i, [])
go i s (x:xs) =
if x `Set.member` s
then go i s xs
else second (x:) $ go (i + 1) (Set.insert x s) xs
{-# INLINEABLE ordNub #-}

{- | @O(n)@.
Removes the first occurrence of the given element from its slist argument.
Expand Down
79 changes: 79 additions & 0 deletions src/Slist/Containers.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{- |
Copyright: (c) 2021 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>
Stability: Stable
Portability: Portable
Useful combinators to work with the data structures from @containers@ package
and 'Slist' together.
@since x.x.x.x
-}
module Slist.Containers
( -- * Map
mapToVals
, mapToKeys
, mapToPairs

-- * Set
, setToSlist
) where

import Data.Map.Strict (Map)
import Data.Set (Set)

import Slist.Size (Size (..))
import Slist.Type (Slist (..))

import qualified Data.Map.Strict as Map
import qualified Data.Set as Set


{- | @O(n)@.
Returns a 'Slist' of all values of the map in the ascending order of their keys.
@since x.x.x.x
-}
mapToVals :: Map k v -> Slist v
mapToVals m = Slist
{ sList = Map.elems m
, sSize = Size $ Map.size m
}
{-# INLINE mapToVals #-}

{- | @O(n)@.
Returns a 'Slist' of all keys of the map in the ascending order.
@since x.x.x.x
-}
mapToKeys :: Map k v -> Slist k
mapToKeys m = Slist
{ sList = Map.keys m
, sSize = Size $ Map.size m
}
{-# INLINE mapToKeys #-}

{- | @O(n)@.
Returns a 'Slist' of all key-value pairs of the map in the ascending order of their keys.
@since x.x.x.x
-}
mapToPairs :: Map k v -> Slist (k, v)
mapToPairs m = Slist
{ sList = Map.toAscList m
, sSize = Size $ Map.size m
}
{-# INLINE mapToPairs #-}

{- | @O(n)@.
Returns a 'Slist' of all elements of the set in the ascending order.
@since x.x.x.x
-}
setToSlist :: Set a -> Slist a
setToSlist s = Slist
{ sList = Set.elems s
, sSize = Size $ Set.size s
}
{-# INLINE setToSlist #-}
14 changes: 13 additions & 1 deletion src/Slist/Maybe.hs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
{- |
Copyright: (c) 2021 Kowainik
SPDX-License-Identifier: MPL-2.0
Maintainer: Kowainik <xrom.xkov@gmail.com>
Maintainer: Kowainik <xrom.xkov@gmail.com>
Stability: Stable
Portability: Portable
Useful 'Maybe' combinators to work with the 'Maybe' data type and 'Slist'
together.
@since x.x.x.x
-}
module Slist.Maybe
( maybeToSlist
Expand All @@ -33,6 +35,8 @@ import qualified Data.Maybe as M
Slist {sList = [42], sSize = Size 1}
>>> maybeToSlist Nothing
Slist {sList = [], sSize = Size 0}
@since x.x.x.x
-}
maybeToSlist :: Maybe a -> Slist a
maybeToSlist = maybe mempty one
Expand Down Expand Up @@ -65,6 +69,8 @@ Reverse is right only on singleton/empty lists
@
maybeToList . slistToMaybe {empty, singleton slist} ≡ {empty, singleton slist}
@
@since x.x.x.x
-}
slistToMaybe :: Slist a -> Maybe a
slistToMaybe = foldr (const . Just) Nothing
Expand All @@ -77,6 +83,8 @@ slistToMaybe = foldr (const . Just) Nothing
>>> catMaybes (cons (Just 1) $ cons Nothing $ one $ Just 3)
Slist {sList = [1,3], sSize = Size 2}
@since x.x.x.x
-}
catMaybes :: Slist (Maybe a) -> Slist a
catMaybes = mapMaybe id
Expand All @@ -97,6 +105,8 @@ If we map the 'Just' constructor, the entire list should be returned:
>>> mapMaybe Just s
Slist {sList = [1,2,3], sSize = Size 3}
@since x.x.x.x
-}
mapMaybe :: forall b a . (a -> Maybe b) -> Slist a -> Slist b
mapMaybe _ (Slist [] _) = mempty
Expand All @@ -115,6 +125,8 @@ mapMaybe f (Slist (x:xs) n) = case f x of
>>> slistWith maybeEven [1,2,3]
Slist {sList = [2], sSize = Size 1}
@since x.x.x.x
-}
slistWith :: forall b a . (a -> Maybe b) -> [a] -> Slist b
slistWith f l = let (n, sl) = go 0 l in Slist sl (Size n)
Expand Down

0 comments on commit bf84c7d

Please sign in to comment.