Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Noel Welsh
    @noelwelsh
    The way this will be done in the future is to use the Parallel construct.
    It's somewhat usable in Cats right now, but the interface can get a bit awkward.
    Alexandr
    @AlexandrSokolov

    @noelwelsh , here is a solution, I tried to apply to compose failfast with failslow:

      import cats.syntax.either._
      import cats.instances.list._ // for Semigroupal
      def oneDateAfterAnotherFailSlow(dateBefore:String, dateAfter:String)
                                     (map: Map[String, String])(format: SimpleDateFormat)
      : FailFast[Tuple2[Date, Date]] =
        for {
          t <-Semigroupal[FailSlow].product(
              readDate(dateBefore)(map)(format).toValidated,
              readDate(dateAfter)(map)(format).toValidated
            ).toEither
          r <- oneAfterAnother(t._1, t._2)
        } yield r

    Can you please comment it, how it looks, is it clear, is there a better approach?

    and small description: The idea, is that first validations for strings are applied, to make sure dates are correct. They are accumulated with Validated(FailSlow). Then fail-fast is used, cause if any of the dates is wrong and cannot be parsed, it makes no sense to continue and to compare them as dates.
    Alexandr
    @AlexandrSokolov

    Hi all,
    A question with Readers.
    Here is a simple service example, whose methods return reader:

        trait Service1_1{
          def s1f1:Reader[Map[String,Int],Int] =
            Reader(_("name"))
    
          def s1f2:Reader[Map[String,Int],Int] =
            Reader(_("age"))
        }

    Here is a service-consumer, that accepts parameter, map, and also returns reader itself:

        trait Service1_2 {
          def s12f1(i:Int, map:Map[String,Int]):Reader[Service1_1, Int] =
            Reader(s => {
              val r = for {
                r1 <- s.s1f1
                r2 <- s.s1f2
              } yield r1 + r2
              r.run(map) + i
            })
        }

    Ok, to use Service1_2.s12f1 I must have map in the parameter list:

        object s1 extends Service1_1
        object s2 extends Service1_2
        val r = s2.s12f1(3, Map("age"-> 1, "name"-> 2)).run(s1)

    The question: how to implement Service1_2.s12f2:

        trait Service1_2 {
          def s2f2 = ???
        }

    In order to be able to run it like:

        s2.s2f2(2)
          .run(s1)
          .run(Map("age"-> 1, "name"-> 2))

    Cannot get it.

    Alexandr
    @AlexandrSokolov

    I could implement it:

         def s2f2(i:Int): Reader[Service1_1, Reader[Map[String,Int],Int]] =
            Reader(s => Reader(map => {
              val r = for {
                r1 <- s.s1f1
                r2 <- s.s1f2
              } yield r1 + r2
              r.run(map) + i
            }))

    The question, is there a better approach? Or at least syntax? Cause with several levels of dependency, it will look strange.

    Probably you can recommend some blogs or articles. But please not just to simple description of the reader with one level of dependency.
    Alexandr
    @AlexandrSokolov

    Hi guys, theoretical question:

    When we implement DI via Reader, we make a dependency a part of our method signature. Assume we have (without implementations):

    trait Service1 { def f1:Int = ??? }
    trait Service2 { def f2:Reader[Service1, Int] = ??? }
    
    type Env= (Service1, Service2)
    def c:Reader[Env, Int] = ???  //use Service2.f2 here

    Now, f2 needs additional service for implementation, say:

    trait Service3
    type Service2Env = (Service1, Service3)
    //new dependecies on both:
    trait Service2 { def f2:Reader[Service2Env, Int] = ??? }

    It will break existing clients, they cannot any longer to use Service2.f2 without providing Service3 additionally.

    With DI via injection (via constructor or setters), which is common in OOP, I would use in a dependency only Service2. How it is constructed and what is its list of dependencies, I do not care. From this point, any new dependencies in Service2 will keep the signature of c function unchanged.

    How is it solved in FP? Are there options? Is there a way to inject new dependencies, but somehow protect customers from the change?

    Abhishek Srivastava
    @abhishes_twitter
    I would use a case class in the signature
    then Service3 can be a Option (default None) in the case class.
    This will be a reasonable approach to refactor the code without breaking existing clients
    Anthony Michaelson
    @anthonymichaelson_gitlab
    RE: Bridges; is that library currently being utilized in any SBT plugins to watch source files and output to the desired target languages (typescript, elm, flow)?
    Harit Himanshu
    @hhimanshu

    Hello there, I am reading the build.sbt for Scala and looking at code like

    publishArtifact in (Compile, packageDoc)

    and

    packageOptions in Compile in packageSrc

    Do they both mean the same things as I read code? That is Compile:packageDoc::publishArtifact and Compile:packageSrc::packageOptions?

    Sachin Kukreja
    @sk364
    Hello.
    Can anyone help me to understand why there is a limit of 22 elements for a tuple?
    Abhishek Srivastava
    @abhishes_twitter
    nafg
    @nafg
    @sk364 the reason why is that each size tuple is hard coded as a case class in the standard library
    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)
    Sachin Kukreja
    @sk364
    Thanks. And that's awesome that it's getting dropped.
    Though, I am trying to understand why the number "22" is the limit?
    Noel Welsh
    @noelwelsh
    22 is just an arbitrary number that was considered big enough.
    More recent versions of Scala drop that limit IIRC.
    nafg
    @nafg
    I think you're thinking of case classes
    The tuple limit is only dropped in dotty
    Noel Welsh
    @noelwelsh
    Gotcha
    Sachin Kukreja
    @sk364
    I was just wondering, if there was some logical analysis behind choosing the number 22, which I am unable to see.
    I am guessing the architecture of the tuples is such that more than 22 elements is too much memory?
    Fabio Labella
    @SystemFw
    no, it's arbitrary
    the way tuples and functions are encoded are with a bunch traits, Tuple1, Tuple2... and so on
    謝宇恆
    @xieyuheng
    22 is the secret seed for the finial answer, 22 + 22 - 2 = 42
    Noel Welsh
    @noelwelsh
    :boom:
    Shouvik Roy
    @royshouvik
    Just wanted to drop by and thank the authors and everyone behind the Creative Scala book. I am really enjoying the book :clap:
    Visar Zejnullahu
    @visar
    Hi guys
    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
    Visar Zejnullahu
    @visar
    and I can see that perimeter and area are set to 0
    Any idea why?
    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"