Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Alexandr
    @AlexandrSokolov
    starting working on Scala: first question must be - what is used to build it, maven, sbt or IDE
    Fabio Labella
    @SystemFw

    @AlexandrSokolov as a trick, every time you see:

    required: ?F[?A0]

    with those question marks, it's partial unification

    Alexandr
    @AlexandrSokolov
    Fabio, can we request for such compiler errors a description in the error: 'check if partial unification is enabled'. It will help a lot to analyze and not to guess
    Fabio Labella
    @SystemFw
    well, in 2.13 this error won't happen again so...
    mmynsted
    @mmynsted
    @AlexandrSokolov How often do you find that you must not have partial unification enabled?
    Seems like a reasonable default for most new code.
    Noel Welsh
    @noelwelsh
    Well, glad you got it working.
    Alexandr
    @AlexandrSokolov

    Hi guys!
    I am still playing with validations. A couple of questions. Is there a key difference between using Semigroupal.product and Semigroupal.tuple2. In the first case it is trait, in the 2nd it is object.

    import cats.Semigroupal
    import cats.data.Validated
    import cats.data.Validated.Invalid
    import cats.instances.list._ // for Monoid
    
      type AllErrorsOr[A] = Validated[List[String], A]
      def bothInvalid = {
        Semigroupal[AllErrorsOr].product(
          Validated.invalid(List("Error 1")),
          Validated.invalid(List("Error 2"))
        )
      }
    
      def bothInvalidTuple = {
        Semigroupal.tuple2(
          Validated.invalid(List("Error 1")),
          Validated.invalid(List("Error 2"))
        )
      }
    
      def bothValid = {
        Semigroupal[AllErrorsOr].product(
          Validated.valid(10),
          Validated.valid(20)
        )
      }
    
      def bothValidTuple = {
        Semigroupal.tuple2(
          Validated.valid(10),
          Validated.valid(20)
        )
      }

    With invalids both bothInvalid and bothInvalidTuple give the same result. With valid values, only the first one is compiled. The error I am getting:

    Error:(40, 23) could not find implicit value for parameter semigroupal: cats.Semigroupal[[+A]cats.data.Validated[Nothing,A]]
        Semigroupal.tuple2(

    As I understand it now: In order to use Semigroupal.product, I neen an instance of Validated, which I get through:

    import cats.data.Validated
    import cats.data.Validated.Invalid

    with Semigroupal.tupleN I need in the scope to have an implicit instance of Validated??? But it seems I already have it with the previous imports, right? What do I miss?

    Alexandr
    @AlexandrSokolov

    Exactly this issue is described in the Scala with Cats book, p. 155:

    Validated accumulates errors using a Semigroup , so we need one of those in scope to summon the Semigroupal . If no Semigroup is visible at the call site, we get an annoyingly unhelpful compila on error:

    But I do not get it, where can I find Semigroup for positive Validated, if not in cats.data.Validated

    Noel Welsh
    @noelwelsh
    You need a Semigroup instance for the type that holds the errors. E.g. in your case you need the Semigroup for List.
    Alexandr
    @AlexandrSokolov
    @noelwelsh , it is already in the scope: import cats.instances.list._ // for Monoid
    Alexandr
    @AlexandrSokolov
    I think an issue here, that according to the error, it searchs for Monoid for Nothing:
    cats.Semigroupal[[+A]cats.data.Validated[Nothing,A]]
    And I must somehow say, that actual type is AllErrorsOr
    Validated[List[String], A], but not cats.data.Validated[Nothing,A]]
    Alexandr
    @AlexandrSokolov

    @noelwelsh , one more question, I am looking at example from the book:

    case class User(name: String, age: Int)
    def readName(data: FormData): FailFast[String]...
    def readAge(data: FormData): FailFast[Int] ...
    ...
    def readUser(data: FormData): FailSlow[User] =
    (
      readName(data).toValidated,
      readAge(data).toValidated
    ).mapN(User.apply)

    Let's assume I have another function for validation, that accepts name and age, validated by readName and readAge. For intstance:
    def validBoth(name:String, age:Int):FailFast[Tuple2[String,Int]]

    How to compose these functions together? I cannot use mapN, cause it require function, that does return raw value (not the context, in out case, not Validated). At least it did not work.
    With fail fast it is quite simple, cause I use for-comrehension and have access to the results of readName and readAge:

    for {
      n <- readName...
      i <-  readAge...
      t <- validBoth(n,i)
    } yield t

    but how to get the same result for failslow? Cause in this context it makes much more sense. validBoth - returns FailFast, but the whole composition should be failSlow

    Alexandr
    @AlexandrSokolov
    I need something like flatMap2, then I can write:
    flatMap2(readName(), readAge())(validBoth(_,_))
    But where can I get it?:) Or I am moving in the wrong direction?
    Noel Welsh
    @noelwelsh
    This message was deleted
    I think there is a method called andThen or similar on Validated that does what you're looking for.
    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
    Naftoli Gugenheim
    @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.
    Naftoli Gugenheim
    @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