Skip to content
This repository was archived by the owner on Oct 4, 2020. It is now read-only.

Commit 74c05d4

Browse files
pseudonomhdgarrood
authored andcommitted
Added subset, properSubset, and intersection.
1 parent ab0fabc commit 74c05d4

File tree

1 file changed

+43
-0
lines changed

1 file changed

+43
-0
lines changed

src/Data/Set.purs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ module Data.Set
1919
, union
2020
, unions
2121
, difference
22+
, subset
23+
, properSubset
24+
, intersection
2225
) where
2326

2427
import Prelude
@@ -29,6 +32,17 @@ import Data.Monoid (Monoid)
2932
import Data.Tuple (fst)
3033
import 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`
3347
data Set a = Set (M.Map a Unit)
3448

@@ -111,3 +125,32 @@ unions = foldl union empty
111125
-- | Form the set difference
112126
difference :: forall a. (Ord a) => Set a -> Set a -> Set a
113127
difference 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

Comments
 (0)