Skip to content

Instantly share code, notes, and snippets.

@erdeszt
Last active November 14, 2022 21:31
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erdeszt/ce2eeadc36311e49126e07c7c2c43de5 to your computer and use it in GitHub Desktop.
Save erdeszt/ce2eeadc36311e49126e07c7c2c43de5 to your computer and use it in GitHub Desktop.
Scala 3 zio rich newtype improvements
import zio.prelude.Newtype
import cats.Contravariant
import cats.Functor
import cats.syntax.contravariant.*
import cats.syntax.functor.*
import io.circe.*
import io.circe.syntax.*
import io.circe.parser.decode
abstract class RichNewtypeOld[T, Unwrapped[_]: Functor, Wrapped[_]: Contravariant]()(
using unwrapped: Unwrapped[T], wrapped: Wrapped[T]
) extends Newtype[T] {
implicit val unwrappedNewtype: Unwrapped[Type] = unwrapped.map(wrap(_))
implicit val wrappedNewtype: Wrapped[Type] = wrapped.contramap(unwrap(_))
}
trait DeriveFunctor1[T, F[_]: Functor](using f: F[T]) { self: Newtype[T] =>
implicit val derivedFunctor1: F[Type] = f.map(_.asInstanceOf[Type]) // NOTE: should use wrap but "illegal access" so inlined it
}
trait DeriveContravariant1[T, F[_]: Contravariant](using f: F[T]) { self: Newtype[T] =>
implicit val derivedContravariant1: F[Type] = f.contramap(unwrap(_))
}
object Name extends Newtype[String]
with DeriveFunctor1[String, Decoder]
with DeriveContravariant1[String, Encoder]
type Name = Name.Type
object Age extends RichNewtypeOld[Int, Decoder, Encoder]
type Age = Age.Type
trait RichNewtype[T, Unwrapped[_], Wrapped[_]] extends Newtype[T] /*with DeriveFunctor1[T, Unwrapped]*/ with DeriveContravariant1[T, Wrapped]
println(s"YO: ${Name("Foo").asJson.noSpaces} is ${Age(29).asJson.noSpaces} years old")
println(s"Decoder works too: ${decode[Name](""""Foo"""")}, ${decode[Age]("29")}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment