## Where communities thrive

• Join over 1.5M+ people
• Join over 100K+ communities
• Free without limits
##### Activity
SuprF1y
@SuprF1y

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.

Marjan Mubarok
@MarjanMubarok
Hello, I plan on doing a presentation on the different ways Scala supports concurrency. Does anyone know of any good books on the topic?
Charis Loveland
@charislove
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."
Noel Welsh
@noelwelsh
Thanks @charislove !
georgreen
@georgreen

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â€ť.

Fabio Labella
@SystemFw
I don't really have time for a full explanation, but you can look up "negative and positive position"
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
georgreen
@georgreen
@SystemFw, thank you.
Fabio Labella
@SystemFw

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

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
@msali123
Hi
I'm new here. Is there any way to host a project built with scala. On github pages or etc?
nano
@mr-nano
Hey folks. Glad to find this channel. Wish for everyone's safety in this crazy virus time!
Noel Welsh
@noelwelsh
:+1:
@eusojk
Hi all,
I just started my Scala/FP learning journey with Creative Scala. Very fantastic and engaging so far :raised_hands: !
For some reason, the images (figures) on the website don't render for me. I've tried multiple browsers with no luck. Has anyone experienced this by any chance? Thanks in advance!
@arosien
@eusojk no, you're right, the images for the book on creativescala.com aren't loading. i'll let @noelwelsh know! thanks
@eusojk
Thanks @arosien, appreciate it!
Noel Welsh
@noelwelsh
Thanks for letting me know. I don't know why the images aren't working (nothing has changed in the build system) but the system we use to build the books is well past its use by date.
Paul Carey
@paulcarey
hi, what does the [_] before the List in the following refer to?
List(1).withFilter(_ > 0)
val res63: scala.collection.WithFilter[Int,[_]List[_]] = scala.collection.IterableOps\$WithFilter@cf76c0b
@arosien
@paulcarey there are 2 type parameters to WithFilter, and the second one is List[_], where [_] is syntax for "the type parameter is missing". List is a type constructor with one type parameter, and if you supply the type parameter, like Int, you get back a type List[Int].
note this syntax only applies to type parameters. if you have a value parameter def something(list: List[_]), then the [_] is a wildcard, meaning you can pass a list value whose elements are any type.
([_] there means "i don't care what the type is, so i'm going to forget its name", just like _ in places like pattern matching means "i don't care what this is, i'm not even going to name it")
Alan Lewis
@london-coder
Hi All, just joined, so I hope I might get a bit of help, and not offend any members if my enquiry is too simple. I've looked at @davegurnell validation framework. A nice library, that I'm sure is useful in a number of scenarios. However, I have a much simpler need to validate values in a single case class. Is there a 'lighter weight' capability that will be suitable for a smaller requirement?
@arosien
@london-coder you could just use "plain" functions to validate, perhaps in the case class or companion object. the functions could return Either or perhaps cats.Validated
Alan Lewis
@london-coder
Hi @arosien thanks for the quick reply. I'll give that a try. But, I was hoping I could use the validation (of 2 case class field values, and for any duplicate entries) in a for comprehension. Yes, I realise that means the mechanism will require map and flatMap methods.... Therein lies my difficulty. I'm not confident in implementing those methods for non-collection types
@arosien
ah i see. and the flatMap doesn't exist on Validation, and will "fail-fast", when you probably want to collect all the errors

if you use cats you can follow the examples at https://typelevel.org/cats/typeclasses/parallel.html#parallel

basically you write your validation functions to produce Either. but you "glue together" those functions to act using Validated, which then gets converted back to Either at the end

that is, you can't use a for-comprehension if you want to collect all the errors. you need something like mapN from cats. it's like a mode: you switch from fail-fast (flatMap via Either) to collect-errors (mapN via Validated), and back.
@arosien
let me know if any of that makes sense :)
Paul Carey
@paulcarey
@arosien thanks, but doesn't your answer refer to the second [_] in [_]List[_]? I'm wondering about the first one.
@arosien
ah. i think i mentally didn't see the first [_], which is some sort of toString artifact. it's not legal scala syntax.
it should have printed val res63: scala.collection.WithFilter[Int, List] = ... to be correct
(i think)
Paul Carey
@paulcarey
ok, that's what I would have expected. I was a bit puzzled by the preceding [_].
@arosien
yeah, i can guess that there's some anonymous parameter that it is choosing to also anonymize, which makes it extra confusing.
REPL output should be valid REPL input!
Paul Carey
@paulcarey
thanks
"glue together" = more than 1 Either => 1 Either. a for-comprehension does this, but mapN also does it.