@@ -19,6 +19,9 @@ module Data.Set
1919 , union
2020 , unions
2121 , difference
22+ , subset
23+ , properSubset
24+ , intersection
2225 ) where
2326
2427import Prelude
@@ -29,6 +32,17 @@ import Data.Monoid (Monoid)
2932import Data.Tuple (fst )
3033import qualified Data.Map as M
3134
35+ import Control.Monad.Eff (runPure , Eff ())
36+ import Control.Monad.ST (ST ())
37+ import Control.Monad.Rec.Class (tailRecM2 )
38+ import Data.Array (map , nub , length )
39+ import Data.Array.ST
40+ import Data.Either
41+ import Data.Maybe
42+ import Data.Tuple
43+ import Data.Foldable (foldl )
44+ import Prelude.Unsafe (unsafeIndex )
45+
3246-- | `Set a` represents a set of values of type `a`
3347data Set a = Set (M.Map a Unit )
3448
@@ -111,3 +125,32 @@ unions = foldl union empty
111125-- | Form the set difference
112126difference :: forall a . (Ord a ) => Set a -> Set a -> Set a
113127difference s1 s2 = foldl (flip delete) s1 (toList s2)
128+
129+ -- | True if and only if every element in the first set
130+ -- | is an element of the second set
131+ subset :: forall a . (Ord a ) => Set a -> Set a -> Boolean
132+ subset s1 s2 = isEmpty $ s1 `difference` s2
133+
134+ -- | True if and only if the first set is a subset of the second set
135+ -- | and the sets are not equal
136+ properSubset :: forall a . (Ord a ) => Set a -> Set a -> Boolean
137+ properSubset s1 s2 = subset s1 s2 && (s1 /= s2)
138+
139+ -- | The set of elements which are in both the first and second set
140+ intersection :: forall a . (Ord a ) => Set a -> Set a -> Set a
141+ intersection s1 s2 = fromList $ runPure (runSTArray (emptySTArray >>= intersect)) where
142+ ls = toList s1
143+ rs = toList s2
144+ ll = length ls
145+ rl = length rs
146+ intersect :: forall h r . STArray h a -> Eff (st :: ST h | r ) (STArray h a )
147+ intersect acc = tailRecM2 go 0 0 where
148+ go l r =
149+ if l < ll && r < rl
150+ then case compare (ls `unsafeIndex ` l ) (rs `unsafeIndex ` r ) of
151+ EQ -> do
152+ pushSTArray acc (ls `unsafeIndex ` l )
153+ pure $ Left { a : l + 1, b : r + 1}
154+ LT -> pure $ Left { a : l + 1, b : r }
155+ GT -> pure $ Left { a : l , b : r + 1}
156+ else pure $ Right acc
0 commit comments