A set of unique values. Similar to elm/core Set but allows arbitrary data
given a function for converting to comparable
can be provided.
Insert, remove, and query operations all take O(log n) time.
When writing a function for conversion from the type you want to use within a set to comparable it's very important to make sure every distinct member of the type produces different value in the set of comparables. Functions satisfying this property are called injective.
Take for instance those two examples:
We can use store Bool in Set (No matter how unpractical it might seem)
boolToInt : Bool -> Int
boolToInt bool =
case bool of
False -> 0
True -> 1
empty boolToInt
|> insert True
|> member True
--> True
or Maybe String.
comparableKey : Maybe String -> (Int, String)
comparableKey maybe =
case maybe of
Nothing -> (0, "")
Just str -> (1, str)
empty comparableKey
|> insert (Just "foo")
|> member (Just "foo")
--> True
Note that we give Int code to either constructor and in case of Nothing we default to ""
(empty string).
There is still a difference between Nothing
and Just ""
(Int
value in the pair is different).
In fact, you can "hardcode" any value as the second member of the pair
in case of Nothing but empty string seems like a reasonable option for this case.
Generally, this is how I would implement toComparable
function for most of your custom data types.
Have a look at the longest constructor,
Define tuple where the first key is int (number of the constructor)
and other are types within the constructor and you're good to go.
Represents a set of unique values.
Be aware that AnySet stores a function internally.
This means it's not possible to use (==)
for comparing two AnySets.
Use equal function instead.
equal : AnySet comparable t -> AnySet comparable t -> Basics.Bool
Check equality of two AnySet
s
empty : (a -> comparable) -> AnySet comparable a
Create an empty set.
** Note that it's important to make sure every key is turned to different comparable.** Otherwise keys would conflict and overwrite each other.
singleton : a -> (a -> comparable) -> AnySet comparable a
Create a set with one value.
** Note that it's important to make sure every key is turned to different comparable.** Otherwise keys would conflict and overwrite each other.
insert : a -> AnySet comparable a -> AnySet comparable a
Insert a value into a set.
remove : a -> AnySet comparable a -> AnySet comparable a
Remove a value from a set. If the value is not found, no changes are made.
removeAll : AnySet comparable a -> AnySet comparable a
Remove all entries from AnySet.
Useful when you need to create new empty AnySet using same comparable function for key type.
toggle : a -> AnySet comparable a -> AnySet comparable a
Toggle a value in a set. If it's not found, it's inserted, else it's removed.
isEmpty : AnySet comparable a -> Basics.Bool
Determine if a set is empty.
member : a -> AnySet comparable a -> Basics.Bool
Determine if a value is in a set.
get : a -> AnySet comparable a -> Maybe a
Get a value from set.
This is useful in case of AnySet
because
some parts of a value might not be used
for generating comparable.
This function allows quering AnySet
with old
value to obtain updated one in such cases.
size : AnySet comparable a -> Basics.Int
Determine the number of elements in a set.
any : (v -> Basics.Bool) -> AnySet comparable v -> Basics.Bool
Find out if there is any instance of something in a set.
type Animal = Cat | Mouse | Dog
animalToInt : Animal -> Int
animalToInt animal =
case animal of
Cat -> 0
Mouse -> 1
Dog -> 2
animals : AnySet Int Animal
animals =
[ Cat, Mouse ]
|> fromList animalToInt
isACat : Animal -> Bool
isACat animal =
case animal of
Cat -> True
_ -> False
any isACat animals
--> True
all : (v -> Basics.Bool) -> AnySet comparable v -> Basics.Bool
Find out if all values in set match a predicate.
type Animal = Cat | Mouse | Dog
animalToInt : Animal -> Int
animalToInt animal =
case animal of
Cat -> 0
Mouse -> 1
Dog -> 2
animals : AnySet Int Animal
animals =
[ Cat, Mouse ]
|> fromList animalToInt
aristocats : AnySet Int Animal
aristocats =
[ Cat ]
|> fromList animalToInt
isACat : Animal -> Bool
isACat animal =
case animal of
Cat -> True
_ -> False
all isACat animals
--> False
all isACat aristocats
--> True
union : AnySet comparable a -> AnySet comparable a -> AnySet comparable a
Get the union of two sets. Keep all values.
intersect : AnySet comparable a -> AnySet comparable a -> AnySet comparable a
Get the intersection of two sets. Keeps values that appear in both sets.
diff : AnySet comparable a -> AnySet comparable a -> AnySet comparable a
Get the difference between the first set and the second. Keeps values that do not appear in the second set.
symDifference : AnySet comparable a -> AnySet comparable a -> AnySet comparable a
In Math, the symmetric difference of two sets, also known as disjunctive union is the set of elements which are in either of the sets, but not in their intersection. For example, the symmetric difference of the sets {1,2,3} and {3,4} is {1,2,4}.
See https://en.m.wikipedia.org/wiki/Symmetric_difference for more reference.
type Animal = Cat | Mouse | Dog
animalToInt : Animal -> Int
animalToInt animal =
case animal of
Cat -> 0
Mouse -> 1
Dog -> 2
animals : AnySet Int Animal
animals =
[ Cat, Mouse ]
|> fromList animalToInt
moreAnimals : AnySet Int Animal
moreAnimals =
[ Mouse, Dog ]
|> fromList animalToInt
diffAnimals : AnySet Int Animal
diffAnimals =
[ Cat, Mouse, Dog ]
|> fromList animalToInt
symDifference animals moreAnimals == diffAnimals
--> True
toList : AnySet comparable a -> List a
Convert a set into a list, sorted from lowest to highest.
fromList : (a -> comparable) -> List a -> AnySet comparable a
Convert a list into a set, removing any duplicates.
map : (b -> comparable2) -> (a -> b) -> AnySet comparable a -> AnySet comparable2 b
Map a function onto a set, creating a new set with no duplicates.
foldl : (a -> b -> b) -> b -> AnySet comparable a -> b
Fold over the values in a set, in order from highest to lowest.
foldr : (a -> b -> b) -> b -> AnySet comparable a -> b
Fold over the values in a set, in order from lowest to highest.
filter : (a -> Basics.Bool) -> AnySet comparable a -> AnySet comparable a
Only keep elements that pass the given test.
partition : (a -> Basics.Bool) -> AnySet comparable a -> ( AnySet comparable a, AnySet comparable a )
Create two new sets. The first contains all the elements that passed the given test, and the second contains all the elements that did not.
filterMap : (b -> comparable) -> (a -> Maybe b) -> AnySet comparable2 a -> AnySet comparable b
Apply a function that may or may not succeed to all entries in a set, but only keep the successes.
type Animal = Cat | Mouse | Dog
animalToInt : Animal -> Int
animalToInt animal =
case animal of
Cat -> 0
Mouse -> 1
Dog -> 2
animals : AnySet Int Animal
animals =
[ Cat, Mouse ]
|> fromList animalToInt
onlyTom : AnySet String String
onlyTom =
[ "Tom" ]
|> fromList identity
getCatName : Animal -> Maybe String
getCatName animal =
case animal of
Cat -> Just "Tom"
_ -> Nothing
filterMap identity getCatName animals == onlyTom
--> True
toSet : AnySet comparable a -> Set comparable
Convert AnySet to elm/core Set of comparable
decode : (a -> comparable) -> Json.Decode.Decoder a -> Json.Decode.Decoder (AnySet comparable a)
Decode AnySet
from JSON array.
encode : (a -> Json.Encode.Value) -> AnySet comparable a -> Json.Encode.Value
Turn AnySet
into JSON array.