- Join over
**1.5M+ people** - Join over
**100K+ communities** - Free
**without limits** - Create
**your own community**

When you write

`(1, "2", true)`

it's really syntactic sugar for `scala.Tuple3[Int, String, Boolean](1, "2", true)`

That's how scala implements tuples currently, but in the next major version tuples are instead done more like a singly-linked list at the type level (currently it's more analogous to a flat array)

More recent versions of Scala drop that limit IIRC.

The tuple limit is only dropped in dotty

I am guessing the architecture of the tuples is such that more than 22 elements is too much memory?

the way tuples and functions are encoded are with a bunch traits,

`Tuple1`

, `Tuple2`

... and so on
I'm doing Excercise 4.1.4.3 from Essential Scala

```
case class Square(size: Double) extends Rectangular {
val height: Double = size
val width: Double = size
}
```

```
trait Rectangular extends Shape {
def height: Double
def width: Double
val sides: Int = 4
override val perimeter: Double = 2 * (height + width)
override val area: Double = height * width
}
```

```
trait Shape {
def sides: Int
def perimeter: Double
def area: Double
}
```

and in my Main I have this

```
val square = Square(4)
println(square.height)
println(square.width)
println(square.size)
println(square.area)
println(square.perimeter)
println(square.sides)
```

but I'm getting the following results

```
4.0
4.0
4.0
0.0
0.0
4
```

I tried debugging

Any idea why?

`perimeter`

and `area`

should be defined with `def`

as methods rather than as `vals`

```
override def perimeter: Double = 2 * (height + width)
override def area: Double = height * width
```

Another way to do it is declare them `lazy`

. Then they will only be initialised upon first use

```
override lazy val perimeter: Double = 2 * (height + width)
override lazy val area: Double = height * width
```

Due to the immutability of the traits and classes, they will always be the correct value as neither height nor width will be subsequently updated.

Hi, here are some edits for the Atom install documentation. Thank you very much for the hard work on this! At https://www.creativescala.org/creative-scala.html#installing-terminal-software-and-a-text-editors, change "Install Scala support inside Atom: Settings > Install > language-scala" to the following: "Go to atom.io and download and install the Atom text editor. Open Atom and go to the Settings tab. Then click on "+ Install" and type "language-scala" and install."

Works

```
sealed trait Sum[+A, +B] {
def flatMap[AA >: A, C](f: B => Sum[AA, C]): Sum[AA, C] =
this match {
case Failure(v) => Failure(v)
case Success(v) => f(v)
}
}
final case class Failure[A](value: A) extends Sum[A, Nothing]
final case class Success[B](value: B) extends Sum[Nothing, B]
```

Doesn't Work

```
sealed trait Sum[+A, +B] {
def flatMap[C](f: B => Sum[A, C]): Sum[A, C] =
this match {
case Failure(v) => Failure(v)
case Success(v) => f(v)
}
}
final case class Failure[A](value: A) extends Sum[A, Nothing]
final case class Success[B](value: B) extends Sum[Nothing, B]
```

I don't get it. If I take `f: B => Sum[A, C]`

and construct it from `trait Function1[-I, +O]{ def apply(i: I): O}`

it seems `B`

is the contravariant argument while `Sum[A, C]`

is the covariant term in this function. How does it end up that A is the contravariant term also, what does this mean 👇 ?

`"It is declared with type B => Sum[A, C] and thus a supertype is covariant in B and contravariant in A and C."`

I expected it to be `B is the contraviant term`

, why? `it's the argument to function f`

,meaning it's `B`

that has to be type bounded not A and `Sum[A, C] to be covariant`

why? `it's the result type of f`

. But I'm clearly wrong, what I'm I missing here?

I didn't really get the argument for contravariant terms in a function why supertypes?

Source:

"Back to flatMap, the function f is a parameter, and thus in a contravariant position. This means we accept supertypes of f. It is declared with type B => Sum[A, C] and thus a supertype is covariant in B and contravariant in A and C. B is declared as covariant, so that is fine. C is invariant, so that is fine as well. A on the other hand is covariant but in a contravariant position. Thus we have to apply the same solution we did for Box above."

Excerpt From: Noel Welsh and Dave Gurnell. “Essential Scala”.

basically when you nest functions, things switch from positive to negative to positive to negative (and so does their variance)

in this case:

`flatMap`

takes `f`

that returns `Sum`

f: B => Sum[A, C] and construct it from trait Function1[-I, +O]{ def apply(i: I): O} it seems B is the contravariant argument while Sum[A, C] is the covariant term in this function

Right, but now if you write `flatMap`

you `f`

is in turn in negative position, so all the variances switch

This (section of this) article explains it well but it's in Haskell

anyway, I would fully agree it's very confusing

this is tl;dr

```
Positive position: the type variable is the result/output/range/codomain of the function
Negative position: the type variable is the argument/input/domain of the function
When a type variable appears in positive position, the data type is covariant with that variable.
When the variable appears in negative position, the data type is contravariant with that variable.
```

so if you apply these rules and try to work the type of

`flatMap`

out, it should all fit
in

`f`

, `Sum`

is in positive position (return type)`flatMap`

is a function that takes `f`

, so all of `f`

is in negative position, which makes `B`

have positive position and `Sum`

have negative position
which makes it contravariant

the least crap intuition is multiplying numbers by

`1`

and `-1`

, they keep switching. Roughly speaking, functions of functions is the multiplication