6

The three immediate subtypes of Iterable are Map, Seq, and Set. It seems like—aside from performance issues—a Seq is a map from integers to values, and a Set is a map from values to booleans (true if the value is in the set, false otherwise).

If this is the case, why is this not expressed in the type system by making Seq[V] extend Map[Int, V] and Set[V] extend Map[V, Boolean]?

Mechanical snail
  • 29,755
  • 14
  • 88
  • 113
Adam
  • 1,409
  • 12
  • 19

3 Answers3

12

Well, they sort of do, at least actually common functionality. Seq[B] inherits from Int => B (via PartialFunction[Int, B]), Map[A, B] inherits from A => B (also via PartialFunction[A, B]), and Set[A] inherits from A => Boolean. Thus, as far as function application and composition methods are concerned, all three can be used interchangeably. Additionally, they can be used interchangeably as far as traversal goes, as all implement TraversableLike.

kiritsuku
  • 52,967
  • 18
  • 114
  • 136
Dave Griffith
  • 20,435
  • 3
  • 55
  • 76
  • Thanks! In that case, I guess my question shifts a bit: what's the fundamental, 30-words-or-less difference between a Map[A,B] and Function[A,B]? – Adam Apr 01 '11 at 17:24
  • 1
    @Adam A `Map` is traversable, while a `Function` isn't. So a `Map` can enumerate its keys, but a `Function` cannot do the same for its parameters. – Daniel C. Sobral Apr 01 '11 at 18:01
8

Seeing a sequence as an assignment from integers to elements is only one way to describe what a sequence is. There are other ways, and there is no reason why that way of describing a sequence should become canonical. The actual purpose of a sequence is to make a bunch of elements accessible and traversable. A sequence is not required to actually assign integer numbers to the elements. For example, most Stream implementations probably don't have a counter running in parallel to the traversal. Requiring that would impose an unnecessary overhead on the implementation.

Besides, a Map[K,V] is also an Iterable[(K,V)]. Following your suggestion, a Seq[A] would also have to be a Map[Int,A], which would by that also make it an Iterable[(Int,A)]. Since Seq extends Iterable, this would make the Seq[A] both an Iterable[A] and an Iterable[(Int,A)] (and, recursively, an Iterable[(Int,(Int,A))], Iterable[(Int,(Int,(Int,A)))], and so on), which is not an allowed way of inheritance in Scala.

You can construct a similar argument for your suggestion regarding Set.

Madoc
  • 5,841
  • 4
  • 25
  • 38
  • 2
    I think the second argument is compelling. To simplify it, if `Seq[A]` extended `Map[Int,A]`, what would `seq.elements()` return? – Michael Lorton Jan 05 '11 at 04:09
  • Interesting. Haskell's type system suffers from no such limitation (in fact, it flaunts this sort of polymorphism left and right). Interesting to see how Scala's underlying theory has limited its standard library. – Adam Apr 01 '11 at 17:26
  • 1
    @Adam I don't see Haskell getting out of that one either. If you `foldr` as list in Haskell, you don't fold tuples `(Int, A)`: you fold `A`. – Daniel C. Sobral Apr 01 '11 at 17:59
4

Well, if all you care about Seq and Set was that, you'd have a point. Myself, I happen to think that's one of the least importants aspects, and one which is already well represented by all of them being functions.

That is, a Map is a function of a key into a value, a Seq is a function of an Int into a value, and a Set is a function of a value into a Boolean. This property, which you called a "map", is a funciton. And it is already shared by all three.

What, in my opinion, Map, Seq and Set are really about are:

  • A Seq is concerned about knowing in what order its elements are. Conceptually, how would you prepend an element in a Map? You'd have to renumber all keys!

  • A Set is concerned about the presence or absence of an element. How one would model that in a Map? It would have to be a map with default value -- not a common map -- and one in which all non-default values are the same! That is clearly a degenerate behavior, not an abstraction.

  • A Map is concerned about mapping arbitrary keys to arbitrary values. A Seq doesn't have arbitrary keys, and a Set doesn't have arbitrary values.

Daniel C. Sobral
  • 295,120
  • 86
  • 501
  • 681
  • "Well, if all you care about" -- well, my question could be rephrased as "what, specifically, is it that the Scala library designers care about which led them to make this decision"? – Adam Apr 01 '11 at 17:25
  • @Adam See http://www.scala-lang.org/sid/3, http://www.scala-lang.org/docu/files/collections-api/collections.html and http://www.scala-lang.org/docu/files/collections-api/collections-impl.html. – Daniel C. Sobral Apr 01 '11 at 17:57