M80
M80

Reputation: 321

Returning custom sets in scala as an extension of function

I'm trying to write a function that returns a set of integers, when I specify it to as a parameter. I know that in scala, the trait Set[A] extends (A => Boolean), so I tried something like the below:

def foo(x: Int): Set[Int] = {
    return {(y: Int) => y match
        case x => true
        case _ => false
    }
}

But doesn't work, returning

 found   : A => Boolean
 required: Set[A]

Since it isn't in the form it wants, I assume. How can I change my code so it returns a valid set?

Upvotes: 0

Views: 71

Answers (3)

esse
esse

Reputation: 1551

Why not just return a set instance? like this:

Welcome to Scala 2.13.1 (OpenJDK 64-Bit Server VM, Java 1.8.0_222).
Type in expressions for evaluation. Or try :help.

scala> def set(x: Int): Set[Int] = Set(x)
set: (x: Int)Set[Int]

scala> val s = set(1)
s: Set[Int] = Set(1)

scala> s(1)
res0: Boolean = true

scala> s(2)
res1: Boolean = false

Upvotes: 0

Mateusz Kubuszok
Mateusz Kubuszok

Reputation: 27535

Well, Set[A] is a function A => Boolean, true. But it is also a collection that can be traversed, filtered, mapped, etc. You can create something as a function and let the compiler turn it into an object... but only when the type you are implementing that way is single abstract method.

Meanwhile, Set[A] in Scala 2.13 has, well, quite a lot of methods to implement.

    def size: Int
    def isEmpty: boolean
    def knownSize: Int
    def filter(pred: A => Boolean): Set[A]
    def filterNot(pred: A => Boolean): Set[AnyA
    def removedAll(that: IterableOnce[A]): Set[A]
    def diff(that: collection.Set[A]): Set[A]
    def subsetOf(that: collection.Set[A]): Boolean
    def intersect(that: collection.Set[A]): Set[A]
    def view: View[A]
    def contains(elem: A): Boolean
    def incl(elem: A): Set[A]
    def excl(elem: A): Set[A]
    def iterator: Iterator[A]
    def foreach[U](f: A => U): Unit

and how would you create that Set[Int]... would you iterate over all possible Ints? You could make that lazily, but the moment someone called iterator, foreach, etc you would have to materialize these values.

For that reason it is rather unlikely that you will ever use full implementation of Set[Int] materialized from a function Int => Boolean. At best you could implement your own Set implementation that provides only some fraction of the Set interface that doesn't require iterating over whole Int type.

The opposite is trivial though. set.apply(int) is what you are able to do because Set[Int] extends Int => Boolean, so you can assign Set[Int] as a Int => Boolean function.

Upvotes: 2

Mario Galic
Mario Galic

Reputation: 48410

Set[A] is a subtype of A => Boolean, not the other way around

implicitly[Set[Int] <:< (Int => Boolean)]   // OK
implicitly[(Int => Boolean) <:< Set[Int]]   // ERROR

so the following is valid

val s: Int => Boolean = Set(1,2,3)
s(4)
// res0: Boolean = false

but not

val s: Set[Int] = (x: Int) => true   // Error: type mismatch

Upvotes: 2

Related Questions