27
Juliano Alves @vonjuliano juliano-alves.com Shapeless in the real world: An introduction to generic programming.

An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

Juliano [email protected]

Shapeless in the real world:An introduction to generic programming.

Page 2: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

Who am I?● Software Engineer,

Searcher of perfect modularization,Lover of Functional Languages

● The cool onesScala, Clojure, Elixir

● The "vintage" onesJava, C#, Python, Ruby

@vonjulianojuliano-alves.com

Page 3: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

https://getquill.io

Page 4: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect
Page 5: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

https://github.com/juliano/pdt-client

Page 6: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// ZIO Service

object HttpClient { type HttpClient = Has[Service]

trait Service { protected final val rootUrl = "http://www.transparencia.gov.br/api-de-dados/"

def get[T](uri: String, parameters: Map[String, String]) (implicit d: Decoder[T]): Task[T] }

Page 7: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// ZIO Service// Helpers

def get[T](resource: String, parameters: Map[String, String] = Map()) (implicit d: Decoder[T]): RIO[HttpClient, List[T]] = RIO.accessM[HttpClient]( _.get.get[List[T]](resource, parameters))

def get[T](resource: String, id: Long) (implicit d: Decoder[T]): RIO[HttpClient, T] = RIO.accessM[HttpClient]( _.get.get[T](s"$resource/$id", Map()))

Page 8: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// Http4s Implementation

private[client] final case class Http4s(client: Client[Task]) extends HttpClient.Service with Http4sClientDsl[Task] {

def get[T](resource: String, parameters: Map[String, String]) (implicit d: Decoder[T]): Task[T] = { val uri = Uri(path = rootUrl + resource) .withQueryParams(parameters)

client .expect[T](uri.toString()) .foldM(IO.fail(_), ZIO.succeed(_)) }}

Page 9: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// ZIO Service

object HttpClient { // …

def http4s: URLayer[Has[Client[Task]], Has[Service]] = ZLayer.fromService[Client[Task], Service] { http4sClient: Client[Task] => Http4s(http4sClient) }}

Module Pattern

Page 10: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

https://zio.dev/docs/howto/howto_use_layers

Page 11: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

What is the problem?

Page 12: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// ZIO Service

object HttpClient { type HttpClient = Has[Service]

trait Service { protected final val rootUrl = "http://www.transparencia.gov.br/api-de-dados/"

def get[T](uri: String, parameters: Map[String, String]) (implicit d: Decoder[T]): Task[T] }

// Algum clientedef siafi(request: OrgaoRequest): RIO[HttpClient, List[OrgaoSiafi]] = get[OrgaoSiafi]("orgaos-siafi", ???)

Page 13: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// domain.scala

case class OrgaoRequest(codigo: Option[String], descricao: Option[String], pagina: Int = 1)

case class OrgaoSiafi(codigo: String, codigoDescricaoFormatado: String, descricao: String)

case class OrgaoSiape(codigo: String, codigoDescricaoFormatado: String, descricao: String)

Page 14: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// domain.scala

case class OrgaoRequest(codigo: Option[String], descricao: Option[String], pagina: Int = 1) { def toMap: Map[String, String] = ???}

case class OrgaoSiafi(codigo: String, codigoDescricaoFormatado: String, descricao: String)

case class OrgaoSiape(codigo: String, codigoDescricaoFormatado: String, descricao: String)

Page 15: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect
Page 16: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// domain.scala

case class OrgaoRequest(codigo: Option[String], descricao: Option[String], pagina: Int = 1) { def toMap: Map[String, String] = Map("codigo" -> "1337", "descricao" -> "Orgão Federal da Carreta Furacão", "pagina" -> "1")}

Page 17: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect
Page 18: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

Show me the code

Page 19: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// implicits.scala

package object implicits {

implicit class HttpRequestOps[A <: Product](val a: A) { def parameters(implicit toMap: ToMap.Aux[A, Symbol, Any]): Map[String, String] = a.toMap[Symbol, Any] .filter { case (_, v: Option[Any]) => v.isDefined case (_, v) => v != null } .map { case (k, v: Option[Any]) => k.name -> v.get.toString case (k, v) => k.name -> v.toString } }}

Page 20: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// ZIO Service

object HttpClient { type HttpClient = Has[Service]

trait Service { protected final val rootUrl = "http://www.transparencia.gov.br/api-de-dados/"

def get[T](uri: String, parameters: Map[String, String]) (implicit d: Decoder[T]): Task[T] }

Page 21: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

// domain.scala

case class OrgaoRequest(codigo: Option[String], descricao: Option[String], pagina: Int = 1) { def toMap: Map[String, String] = ???}

Page 22: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

object Orgaos {

def siafi(request: OrgaoRequest): RIO[HttpClient, List[OrgaoSiafi]] = get[OrgaoSiafi]("orgaos-siafi", ???)}

object CEISs {

def by(request: CEISRequest): RIO[HttpClient, List[CEIS]] = get[CEIS]("ceis", ???)}

Page 23: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

import pdt.implicits.HttpRequestOps

object Orgaos {

def siafi(request: OrgaoRequest): RIO[HttpClient, List[OrgaoSiafi]] = get[OrgaoSiafi]("orgaos-siafi", HttpRequestOps(request).parameters)}

object CEISs {

def by(request: CEISRequest): RIO[HttpClient, List[CEIS]] = get[CEIS]("ceis", HttpRequestOps(request).parameters)}

Page 24: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

More about shapeless

● https://juliano-alves.com/2020/04/06/shapeless-a-real-world-use-case/The post which inspired this talk

● https://underscore.io/books/shapeless-guide/The Type Astronaut's guide to shapeless

Page 25: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

Conclusion

Page 26: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

Questions?

Page 27: An introduction to generic Shapeless in the real world ...€¦ · Shapeless in the real world: An introduction to generic programming. Who am I? Software Engineer, Searcher of perfect

Juliano [email protected]

Shapeless in the real world:An introduction to generic programming.

Thank you!