Giter Site home page Giter Site logo

glass's People

Contributors

danslapman avatar dependabot[bot] avatar github-actions[bot] avatar odomontois avatar tofu-bot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

narekdw

glass's Issues

Make lenses for Tuple{N}

Let tofu-optics users do this:

import tofu.optics.syntax.tupleN._

val lense = Tuple3._2[Int, String, Long]   // : Contains[(Int, String, Long), String]

tupleN object should contain all possible implicit extensions to Tuple{N} companion objects. Implementations should be macro generated.

Yet Another Lens Macro

I'd like to have more Contains macro generators, covering common use cases.
Few come to mind:

1. A sealed family form for GenContains

example:

sealed trait User{
    def id: String
}

case class Registered(id: String, name: String, email: String) extends User
case class Anonymous(id: String, ip: String) extends User

Here GenContains[User](_.id) must go through all the direct subtypes of User and verify that GenContains(_.id) resolves to lens. Example of generated tree:

val registeredC = GenContains[Registered](_.id)
val anonymousC  = GenContains[Anonymous](_.id)

new Contains[User, String] {
  def set(s: User, b: String) = s match {
    case r: Registered => registeredC.set(r, b)
    case a: Anonymous  => anonymousC.set(a, b)
  }

  def extract(s: User): String = s match {
    case r: Registered => registeredC.extract(r)
    case a: Anonymous  => anonymousC.extract(a)
  }
}

The proposed solution should work even for the case when path is longer that one field, or one of the direct subtypes is a sealed family itself

2. Typeclass based sealed Contains derivation

Ability to derive Contains when each alternative has implicit Contains to the given type.
In the best form it should support recursion and GADTs

 
case class Path(str: String)

sealed trait ValidatedField[A] {
  def check[B](f: A => Either[String, B]): ValidatedField[B] = Check(this, f)
}

@ClassyOptics
case class Read(path: Path) extends ValidatedField[String]

@Optics
case class Check[A, B](inner: ValidatedField[A], verify: A => Either[String, B]) extends ValidatedField[B]

implicit def checkPath[A, B]: Contains[Check[A, B], Path] = Check.inner >> validatedPath

implicit def validatedPath[A]: Contains[ValidatedField[A], Path] = DeriveContains[ValidatedField[A], Path]

latter should be expanded to

implicit def validatedPath[A]: Contains[ValidatedField[A], Path] = {
  new Contains[ValidatedField[A], Path] {
    def set(s: ValidatedField[A], b: Path): ValidatedField[A] = s match {
      case r: Read        => Contains[Read, Path].set(r, b)
      case c: Check[x, A] => Contains[Check[x, A], Path].set(c, b)
    }

    def extract(s: ValidatedField[A]): Path = s match {
      case r: Read        => Contains[Read, Path].extract(r)
      case c: Check[x, A] => Contains[Check[x, A], Path].extract(c)
    }
  }
}

3. Typeclass based case class to case class derivation

When two case classes have fields related to each other, sometimes we can derive Contains for them. Such case could be a partial replacement for complex data transformation libraries such as https://github.com/scalalandio/chimney

We will derive Contains[A, B] when :

  1. Each field in B has a field with the same name in the A
  2. For any two fields with the same name of types AF and BF we have AF =:= BF or Contains[AF, BF]
    Latter could be relaxed providing implicit `Contains[A, A] during derivation
case class RichName(name: String, searchId: Long)
object RichName {
  implicit val nameString: Contains[RichName, String] = GenContains.apply(_.name)
}

case class UserData(
    firstName: String,
    lastName: String,
    age: Int
)

case class UserInfo(
    id: Long,
    firstName: RichName,
    lastName: RichName,
    age: Int,
    lastUpdated: Instant,
)

val infoData = DeriveContains[UserInfo, UserData]

last line should be expanded to the following

val infoData = new Contains[UserInfo, UserData] {
  implicit def sameConv[A]: A Contains A = Same.id

  def set(s: UserInfo, b: UserData): UserInfo =
    s.copy(
      firstName = Contains[RichName, String].set(s.firstName, b.firstName),
      lastName = Contains[RichName, String].set(s.lastName, b.lastName),
      age = Contains[Int, Int].set(s.age, b.age),
    )

  def extract(s: UserInfo): UserData = UserData(
    firstName = Contains[RichName, String].extract(s.firstName),
    lastName = Contains[RichName, String].extract(s.lastName),
    age = Contains[Int, Int].extract(s.age)
  )
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.