Skip to content

Instantly share code, notes, and snippets.

@nicola88
Last active March 20, 2019 22:02
Show Gist options
  • Save nicola88/4778c21bdfbc429dc0ea6b16ec9ffd36 to your computer and use it in GitHub Desktop.
Save nicola88/4778c21bdfbc429dc0ea6b16ec9ffd36 to your computer and use it in GitHub Desktop.
w3-intset
package funsets
/**
* 2. Purely Functional Sets.
*/
object FunSets {
/**
* We represent a set by its characteristic function, i.e.
* its `contains` predicate.
*/
type Set = Int => Boolean
/**
* Indicates whether a set contains a given element.
*/
def contains(s: Set, elem: Int): Boolean = s(elem)
/**
* Returns the set of the one given element.
*/
def singletonSet(elem: Int): Set = (x: Int) => x == elem
/**
* Returns the union of the two given sets,
* the sets of all elements that are in either `s` or `t`.
*/
def union(s: Set, t: Set): Set = (x: Int) => s(x) || t(x)
/**
* Returns the intersection of the two given sets,
* the set of all elements that are both in `s` and `t`.
*/
def intersect(s: Set, t: Set): Set = (x: Int) => s(x) && t(x)
/**
* Returns the difference of the two given sets,
* the set of all elements of `s` that are not in `t`.
*/
def diff(s: Set, t: Set): Set = (x: Int) => s(x) && !t(x)
/**
* Returns the subset of `s` for which `p` holds.
*/
def filter(s: Set, p: Int => Boolean): Set = (x: Int) => s(x) && p(x)
/**
* The bounds for `forall` and `exists` are +/- 1000.
*/
val bound = 1000
/**
* Returns whether all bounded integers within `s` satisfy `p`.
*/
def forall(s: Set, p: Int => Boolean): Boolean = {
def iter(a: Int): Boolean = {
if (a == bound + 1) true
else if (s(a) && !p(a)) false
else iter(bound + 1)
}
iter(-bound)
}
/**
* Returns whether there exists a bounded integer within `s`
* that satisfies `p`.
*/
def exists(s: Set, p: Int => Boolean): Boolean = !forall(s, (x: Int) => !p(x))
/**
* Returns a set transformed by applying `f` to each element of `s`.
*/
def map(s: Set, f: Int => Int): Set = (x: Int) => if s(x) s(f(x))
/**
* Displays the contents of a set
*/
def toString(s: Set): String = {
val xs = for (i <- -bound to bound if contains(s, i)) yield i
xs.mkString("{", ",", "}")
}
/**
* Prints the contents of a set on the console.
*/
def printSet(s: Set) {
println(toString(s))
}
}
abstract class IntSet {
def incl(x: Int): IntSet
def contains(x: Int): Boolean
def union(other: IntSet): IntSet
}
class NonEmpty(elem: Int, left: IntSet, right: IntSet) extends IntSet {
def contains(x: Int): Boolean =
if (x < elem) left contains x
else if (x > elem) right contains x
else true
def incl(x: Int): IntSet =
if (x < elem) new NonEmpty(elem, left incl x, right)
else if (x > elem) new NonEmpty(elem, left, right incl x)
else this
def union(other: IntSet): IntSet =
override def toString = "{" + left + elem + right + "}"
}
object Empty extends IntSet {
def contains(x: Int ): Boolean = false
def incl(x: Int ): IntSet = new NonEmpty(x, Empty, Empty)
def union(other: IntSet): IntSet =
other
override def toString = "."
}
val t1 = new NonEmpty(3, Empty, Empty)
val t2 = t1 incl 4
println(t2)
trait List[T] {
def isEmpty: Boolean
def head: T
def tail: List[T]
}
class Cons[T](val head: T, val tail: List[T]) extends List[T] {
def isEmpty = false
}
class Nil[T] extends List[T] {
def isEmpty: Boolean = true
def head: Nothing = throw new NoSuchElementException("Nil.head")
def tail: Nothing = throw new NoSuchElementException("Nil.tail")
}
def singleton[T](elem: T) = new Cons[T](elem, new Nil[T])
singleton(1)
def nth(n: Int, list: List[Int]): Int =
if (list.isEmpty) throw new IndexOutOfBoundsException("...")
else if (n == 0) list.head
else nth(n - 1, list.tail)
println(nth(0, new Cons(1, new Cons(2, new Nil))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment