Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
    Cary Robbins
    @carymrobbins
    I can envision some sort of newtype-shapeless library that produces Generic instances for newtypes
    Oh I just realized I mixed up your two types. The above may still be a good idea, but not useful for your problem
    Cary Robbins
    @carymrobbins

    @BenShaw You can derive circe instances like this -

    object healthcheck {
      @newtype case class PostgresStatus(value: Boolean)
      object PostgresStatus {
        // The `deriving` name here is magically available here in the
        // companion object thanks to the @newtype macro.
        implicit val circeEncoder: Encoder[PostgresStatus] = deriving
        implicit val circeDecoder: Decoder[PostgresStatus] = deriving
      }
    }

    You can reduce boilerplate by using scalaz-deriving

    object healthcheck {
      @deriving(Encoder, Decoder)
      @newtype case class PostgresStatus(value: Boolean)
    }
    For details on newtype's built-in deriving mechanism, see https://github.com/estatico/scala-newtype#companion-objects
    Ben Shaw
    @benshaw
    @carymrobbins thankyou for the detailed response
    Cary Robbins
    @carymrobbins
    Took a bit of a derail but hope that helps :wink:
    Timofey
    @GusevTimofey

    Hello everyone!
    I have the case class:

    @newtype case class MyClass(value: BigDecimal)

    Also, I have my decoder:

     def myDecoder[T](...) ...

    In companion object MyClass I got:

    def apply(l: Long): MyClass = MyClass(BigDecimal(l) /100)

    Can I derive myDecoder instance with a deriving that will use my custom apply function? Or maybe there is another way to do it?

    Cary Robbins
    @carymrobbins
    @GusevTimofey what's the type of the decoder?
    Ideally, the decoder is a Functor, so you can .map your apply method over it -
    @newtype case class MyClass(value: BigDecimal)
    object MyClass {
      def apply(l: Long): MyClass = MyClass(BigDecimal(l) /100)
      implicit val decoder: Decoder[MyClass] = longDecoder.map(apply)
    }
    Timofey
    @GusevTimofey
    @carymrobbins it's MyDecoder[MyClass]
    Yeap, I'm doing like that right now, but I thought that there is a pretty way of deriving my decoder without mapping
    Cary Robbins
    @carymrobbins
    Unfortunately no, especially because you are wanting to derive from a decoder which is for a different type than the underlying type of your newtype
    Timofey
    @GusevTimofey
    @carymrobbins ok, thanks a lot for helping!
    Cary Robbins
    @carymrobbins
    Sure thing! Also, I changed implicit def to implicit val in my example, so be sure to use that insteaad so you aren't recomputing the decoder each time.
    @GusevTimofey Depending on your situation, you could define a type class/decoder builder to do the derivation for you. Not sure that this will be less boilerplate that just using .map though. Untested example -
    @newtype case class MyClass(value: BigDecimal)
    object MyClass {
      def apply(l: Long): MyClass = MyClass(BigDecimal(l) /100)
      implicit val smartCtor: SmartCtor[Long, BigDecimal] = apply(_)
      implicit def decoder: Decoder[MyClass] = deriveDecoder[Long, MyClass]
    }
    
    def deriveDecoder[A, B](
      implicit decoder: Decoder[A], smartCtor: SmartCtor[A, B]
    ): Decoder[B] = decoder.map(smartCtor.run)
    
    trait SmartCtor[A, B] {
      def run(a: A): B
    }
    Timofey
    @GusevTimofey
    @carymrobbins looks like using .map is simpler
    Cary Robbins
    @carymrobbins
    :tada:
    Cary Robbins
    @carymrobbins
    @bhgitgit put the triple backticks on a single line by themselves :wink:
    image.png
    This message was deleted
    also, could you paste the error message?
    Ryan Mehri
    @rmehri01
    Hello, sorry this is probably asked a lot but I'm working through pfp in scala and I noticed that recently the readme was changed to not recommend the coercible instance trick but I find that explicitly defining the codec instances is somewhat clunky, so is there an alternative easier way to define these codecs and what are the problems with the trick besides increased compile times. Thanks!
    Cary Robbins
    @carymrobbins
    @rmehri01 I should add to the readme that you can use scalaz-deriving to get a less boilerplate-y way to derive newtype instances
    @deriving(Encoder, Decoder)
    @newtype case class Bar(s: String)
    Ryan Mehri
    @rmehri01
    Ah okay, that looks pretty good. Thanks!
    ThomasGrt
    @ThomasGrt

    Hi and first of all thanks for the lib!

    Is it possible to have the newtype instances derivation outside of the newtype companion object?
    I ask this because I'm building a lib and I would like to let the clients of the lib (other processes) add the type class they need in their code.

    I saw something like this on the project readme

    object EqOrphans {
      implicit val eqFoo: Eq[Foo] = implicitly[Eq[Int]].coerce
    }

    but when I try it gives me an error :
    Error:(14, 53) could not find implicit value for parameter ev: io.estatico.newtype.Coercible[cats.Eq[Int],B]
    implicit val eqFoo: Eq[Foo] = implicitly[Eq[Int]].coerce

    Thanks in advance for your help

    Cary Robbins
    @carymrobbins
    @ThomasGrt Same implicit rules should apply. Make sure your orphan instance is in the implicit search scope. This may mean having to explicitly import it, e.g. import EqOrphans.eqFoo or import EqOrphans._
    ThomasGrt
    @ThomasGrt

    Thanks for your quick answer!
    Sorry I must be doing something wrong but I cannot see what...

    This compiles :

    object NewTypeEq extends App {
      import cats.Eq
      import io.estatico.newtype.macros.newtype
      import io.estatico.newtype.ops._
      import cats._, cats.implicits._
    
      @newtype case class Foo(x: Int)
      object Foo {
        implicit val eqFoo: Eq[Foo] = implicitly[Eq[Int]].coerce
      }
    
      println(Foo(1) === Foo(2))
    }

    this does not compile :

    object NewTypeEq2 extends App {
      import cats.Eq
      import io.estatico.newtype.macros.newtype
      import io.estatico.newtype.ops._
      import cats._, cats.implicits._
    
      @newtype case class Foo(x: Int)
    
      object EqOrphans {
        implicit val eqFoo: Eq[Foo] = implicitly[Eq[Int]].coerce
      }
    
      import EqOrphans._
      println(Foo(1) === Foo(2))
    }

    Error is on line

     implicit val eqFoo: Eq[Foo] = implicitly[Eq[Int]].coerce

    could not find implicit value for parameter ev: io.estatico.newtype.Coercible[cats.Eq[Int],B]

    ThomasGrt
    @ThomasGrt
    looks like it works with :
    object EqOrphans {
        import Foo._
        implicit val eqFoo: Eq[Foo] = implicitly[Eq[Int]].coerce
      }
    Łukasz Drygała
    @ldrygala

    Hi
    I'm trying to use a newtype instead of AnyVal in my code. I have a problem with slick column mappers:

    @newtype case class MyId(id: Long)
    
    implicit lazy val myIdMapper: JdbcType[MyId] =
      MappedColumnType.base[MyId, Long](
        _.id,
        MyId.apply
      )

    it fails with:
    No ClassTag available for MyId
    [error] MappedColumnType.base[MyId, Long](

    is there any way to generate ClassTag?

    Cary Robbins
    @carymrobbins

    @ldrygala Hmm may need to just derive it. Maybe try -

    import io.estatico.newtype.ops._
    
    implicit lazy val myIdMapper: JdbcType[MyId] = implicitly[JdbcType[Long]].coerce[JdbcType[MyId]]

    Not sure if lazy is actually needed here. Also not sure if this breaks some invariants about slick.

    If you can, you can derive this in the newtype companion
    @newtype case class MyId(id: Long)
    object MyId {
      implicit lazy val jdbcType: JdbcType[MyId] = deriving
    }
    I don't think generating a ClassTag is correct since MyId doesn't really correspond to a Class
    Łukasz Drygała
    @ldrygala
    thanks @carymrobbins for help
    Cary Robbins
    @carymrobbins
    @ldrygala For sure, did that work out for you?
    Jonas Hoffmann
    @jhoffmann87_gitlab
    Hi, I'm wondering how newtype compares to Scala's value classes. Why should I use newtype over value classes? When should I avoid using newtype?
    Dmytro Mitin
    @DmytroMitin
    @jhoffmann87_gitlab value classes have many limitations https://docs.scala-lang.org/overviews/core/value-classes.html
    Gabriel Volpe
    @gvolpe

    Hey @carymrobbins wondering if you have any clue why this would happen? (cross-posting from the Shapeless room)

    This compiles:

    sealed trait Yay
    object Yay {
      @newtype case class MyId(value: java.util.UUID)
    
      case class Foo(x: Int) extends Yay
      case class Bar(y: Yay.MyId, z: String) extends Yay
    }
    
    Check[Yay]

    This doesn't:

    sealed trait Yay
    object Yay {
      @newtype case class MyId(value: java.util.UUID)
    
      case class Foo(x: Int) extends Yay
      case class Bar(y: MyId, z: String) extends Yay
    }
    
    Check[Yay]

    The only difference is the type that Bar takes, MyId vs Yay.MyId. One compiles, the other doesn't. The implementation of Check relies on some Shapeless stuff, here's a Scastie that quickly demonstrates the issue: https://scastie.scala-lang.org/6TZGnRWIRDCBQxYDPOYreA

    Could it be macro expansion kicks in after Shapeless processes the datatypes?

    Cary Robbins
    @carymrobbins

    @gvolpe I'm not sure, but I'm betting that the bug is somewhere in either the implementation of Check or the shapeless side of things.

    You can use @newtype(debug=true) case class MyId(value: java.util.UUID) to have the compiler spit out the generated Scala code. By replacing the macro invocation with the generated Scala, we can rule out macro expansion.

    sealed trait Yay
    object Yay {
      //@newtype(debug=true) case class MyId(value: java.util.UUID)
      type MyId = MyId.Type
      object MyId {
        type Repr = java.util.UUID
        type Base = { type __MyId__newtype }
        trait Tag
        type Type <: Base with Tag
      }
    
      case class Foo(x: Int) extends Yay
      case class Bar(y: MyId, z: String) extends Yay
    }
    
    Check[Yay]
    could not find implicit value for parameter ev: Playground.Check.Checks[Playground.Yay]

    However, if we use

      case class Bar(y: Yay.MyId, z: String) extends Yay

    as you did before, it compiles.

    Gabriel Volpe
    @gvolpe
    Thanks for getting back to me, @carymrobbins. I got a reply in the shapeless room and we minimized the example even further. It's unrelated to newtypes, sorry for the trouble.
    Cary Robbins
    @carymrobbins
    @gvolpe No problem at all, glad you got it worked out.
    Eric Meisel
    @etspaceman

    Hey there. I'm having a hard time converting my library's AnyVal types to use this library and was hoping to get some help.

    Here is an example of a class that I'm attempting to convert: https://github.com/etspaceman/scalacheck-faker/blob/master/src/main/scala/faker/address/BuildingNumber.scala

    My code after the conversion is:

    package faker.address
    
    import org.scalacheck.{Arbitrary, Gen}
    import faker.ResourceLoader
    import faker.syntax.string._
    import io.estatico.newtype.macros.newtype
    
    @newtype final case class BuildingNumber private(value: String)
    
    object BuildingNumber {
      implicit def buildingNumberArbitrary(implicit
          loader: ResourceLoader
      ): Arbitrary[BuildingNumber] =
        Arbitrary(
          Gen
            .sequence[Seq[String], String](
              loader
                .loadKey[Seq[String]]("address.building-numbers")
                .map(_.interpolatedGen)
            )
            .flatMap(x => Gen.oneOf(x).map(apply))
        )
    }

    But I get an error:

    [error] C:\Users\erics\Documents\GitHub\scalacheck-faker\src\main\scala\faker\address\BuildingNumber.scala:8:27: macro annotation could not be expanded (you cannot use a macro annotation in the same compilation run that defines it)
    [error] @newtype final case class BuildingNumber private (value: String)
    [error]

    Pretty confused on what's going on here. Hoping to get some help

    I also tried replacing Gen.oneOf(x).map(apply) with Gen.oneOf(x).coerce but was getting a Coerceable not found error
    Another thing I thought of was to remove uses of the BuildingNumber class from the types itself, so I created a separate module for my types and for the classes / tests that referenced it, but received the same errors
    @carymrobbins I'm sure I'm doing something wrong. Mind guiding me here?
    Cary Robbins
    @carymrobbins
    unfortunately, you can't define a newtype at the top level
    it needs to be nested under an object of some kind
    a package object suffices
    Eric Meisel
    @etspaceman
    Got it. Thanks
    Igal Tabachnik
    @hmemcpy
    Good evening! I was wondering, why couldn't the macro emit a TypeTag that would just summon the Repr's type tag? I guess that's what you'd want to do anyway, right?
    Cary Robbins
    @carymrobbins
    @hmemcpy I think that might not be exactly what we'd want. Ideally, a TypeTag would contain the type information of the type in question, so we'd lose type info that way. If we chose to do what you are saying, it might be preferable to allow people to opt in to it (as a macro parameter or something) that way if we find a better way to do it in the future that doesn't lose type information we won't be stuck with the hack.