# Sets (Free Functions)

In the first article on Sets, we looked at how we might implement a set of integers named IntSet as a function.

The idea is to play around with a different way of looking at something that we think we're familiar with and see what happens.

We easily created sets that were a range of Ints and saw how to form unions and intersections.

I thought that was pretty good. We were able to ask a set if it contained a particular element by evaluate the set with the element as the parameter.

We're going to take this a bit further today. Here's today's sample code and here's the Playground it comes from. Please note that, as the readme and license specify, this is based on code Copyrighted by Graham and is under the MIT license.

Here's our definition of IntSet, a constructor for a set that contains a range of Ints named rangeSet, and a set named twoThreeFour.

I'd actually like a way of displaying the contents of the sets we create. Here's a simple approach that displays all of the sets contents within some bounds. Here I'm defaulting to between 0 and 10 but you can specify different bounds.

Now we can display

The console shows this as [2,3,4].

Remember, twothreefour is just a function Int -> Bool.

We already have union and intersection, it might be nice to have complement. As you'd expect, the complement just returns true if the element is not in the original set.

The complement of twothreefour is an infinite set consisting of all of the numbers less than or equal to 1 and those greater than or equal to 5.

The console shows this as [0, 1, 5, 6, 7, 8, 9, 10].

Yes, I'd prefer that this rendered as {..., 1, 5, ...} or {..., 0, 1, 5, 6, ...}, but I didn't see a quick way of doing this in contents(). (If you have a thought, please share it in the discussion.)

With union, intersection, and complement, we can easily add difference and symmetric difference.

Take these for a test drive.

These both yield [2, 5].

One of you complained that we only have sets of consecutive Ints.

We can now obviously use these different set operations to get sets with gaps in them. Let's also make it easier to create a new IntSet consisting of specified elements.

We can use this to create a set of prime numbers like this.

A set is still a function. The intersection of two sets is also a function. And so on.

For kicks lets find the union of primes and twoThreeFour.

Show the contents of this and see [2, 3, 4, 5, 7]. Note we don't get [2, 3, 5, 7, 2, 3, 4] or [2, 2, 3, 3, 4, 5, 7].

I know that that's obvious, but it means that we get the uniqueness feature of a set for free.

We probably want to be able to add and remove objects. We can implement them like this.

So let's take twothreefour and add 7, then remove 7, and then add it again.

The results are [2, 3, 4, 7], [2, 3, 4], and [2, 3, 4, 7], respectively.

We're checking that if we remove something we've added then it isn't there anymore and then if we add it back that it didn't stay removed.

An IntSet is just a function (Int) -> Bool but we've been able to do a lot of set-like things with it.

This is pretty ugly.

There are a lot of free functions floating around.

Next time, we'll modify our example to make it feel nicer to use.