Skip to content

Commit

Permalink
Merge pull request #863 from typelevel/topic/twiddles-zero-dot-six
Browse files Browse the repository at this point in the history
Update Typelevel Twiddles to 0.6, replacing .as[CaseClass] with .to[CaseClass]
  • Loading branch information
mpilquist authored May 2, 2023
2 parents 454d77e + 5a6443b commit b6c63a7
Show file tree
Hide file tree
Showing 26 changed files with 51 additions and 51 deletions.
2 changes: 1 addition & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ lazy val core = crossProject(JVMPlatform, JSPlatform, NativePlatform)
"org.tpolecat" %%% "natchez-core" % natchezVersion,
"org.tpolecat" %%% "sourcepos" % "1.1.0",
"org.scala-lang.modules" %%% "scala-collection-compat" % "2.10.0",
"org.typelevel" %%% "twiddles-core" % "0.5.0",
"org.typelevel" %%% "twiddles-core" % "0.6.0",
) ++ Seq(
"com.beachape" %%% "enumeratum" % "1.7.2",
).filterNot(_ => tlIsScala3.value)
Expand Down
4 changes: 2 additions & 2 deletions modules/core/shared/src/main/scala-3/syntax/CodecOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,14 @@ class CodecOps[A <: Tuple](self: Codec[A]) {
(other, self).contramapN(t => (t.head, t.tail))

// For binary compatibility with Skunk 0.5 and prior
@deprecated("Use .as[P] instead of .pimap[P]", "0.6")
@deprecated("Use .to[P] instead of .pimap[P]", "0.6")
def pimap[P <: Product](
using m: Mirror.ProductOf[P] { type MirroredElemTypes = A }
): Codec[P] =
self.imap(m.fromProduct)(p => Tuple.fromProductTyped(p))

// For binary compatibility with Skunk 0.3.1 and prior
@deprecated("Use .as[P] instead of .pimap[P]", "0.6")
@deprecated("Use .to[P] instead of .pimap[P]", "0.6")
private[skunk] def pimap[P <: Product](
using m: Mirror.ProductOf[P],
i: m.MirroredElemTypes =:= A
Expand Down
4 changes: 2 additions & 2 deletions modules/core/shared/src/main/scala-3/syntax/DecoderOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ class DecoderOps[A <: Tuple](self: Decoder[A]) {
(other, self).mapN(_ *: _)

// For binary compatibility with Skunk 0.5 and prior
@deprecated("Use .as[P] instead of .pmap[P]", "0.6")
@deprecated("Use .to[P] instead of .pmap[P]", "0.6")
def pmap[P <: Product](
using m: Mirror.ProductOf[P] { type MirroredElemTypes = A }
): Decoder[P] =
self.map(m.fromProduct)

// For binary compatibility with Skunk 0.3.1 and prior
@deprecated("Use .as[P] instead of .pmap[P]", "0.6")
@deprecated("Use .to[P] instead of .pmap[P]", "0.6")
private[skunk] def pmap[P <: Product](
using m: Mirror.ProductOf[P],
i: m.MirroredElemTypes =:= A
Expand Down
4 changes: 2 additions & 2 deletions modules/core/shared/src/main/scala-3/syntax/EncoderOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ class EncoderOps[A <: Tuple](self: Encoder[A]) {
private[syntax] def *:[B](other: Encoder[B]): Encoder[B *: A] =
(other, self).contramapN[B *: A] { case b *: a => (b, a) }

@deprecated("Use .as[P] instead of .pcontramap[P]", "0.6")
@deprecated("Use .to[P] instead of .pcontramap[P]", "0.6")
def pcontramap[P <: Product](
using m: Mirror.ProductOf[P] { type MirroredElemTypes = A }
): Encoder[P] =
self.contramap(p => Tuple.fromProductTyped(p))

// For binary compatibility with Skunk 0.3.1 and prior
@deprecated("Use .as[P] instead of .pcontramap[P]", "0.6")
@deprecated("Use .to[P] instead of .pcontramap[P]", "0.6")
private[skunk] def pcontramap[P <: Product](
using m: Mirror.ProductOf[P],
i: m.MirroredElemTypes =:= A
Expand Down
2 changes: 1 addition & 1 deletion modules/core/shared/src/main/scala/Codec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ trait Codec[A] extends Encoder[A] with Decoder[A] { outer =>
Codec(b => encode(g(b)), emap(f).decode(_, _), types)

/** Adapt this `Codec` from twiddle-list type A to isomorphic case-class type `B`. */
@deprecated("Use (a *: b *: c).as[CaseClass] instead of (a ~ b ~ c).gimap[CaseClass]", "0.6")
@deprecated("Use (a *: b *: c).to[CaseClass] instead of (a ~ b ~ c).gimap[CaseClass]", "0.6")
def gimap[B](implicit ev: Twiddler.Aux[B, A]): Codec[B] =
imap(ev.from)(ev.to)

Expand Down
4 changes: 2 additions & 2 deletions modules/core/shared/src/main/scala/Command.scala
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,11 @@ final case class Command[A](
def contramap[B](f: B => A): Command[B] =
Command(sql, origin, encoder.contramap(f))

@deprecated("Use .as[CaseClass] instead of .gcontramap[CaseClass]", "0.6")
@deprecated("Use .to[CaseClass] instead of .gcontramap[CaseClass]", "0.6")
def gcontramap[B](implicit ev: Twiddler.Aux[B, A]): Command[B] =
contramap(ev.to)

def as[B](implicit ev: Iso[A, B]): Command[B] =
def to[B](implicit ev: Iso[A, B]): Command[B] =
contramap(ev.from)

def cacheKey: Statement.CacheKey =
Expand Down
2 changes: 1 addition & 1 deletion modules/core/shared/src/main/scala/Decoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ trait Decoder[A] { outer =>
emap(a => Either.cond(f(a), a, "Filter condition failed."))

/** Adapt this `Decoder` from twiddle-list type A to isomorphic case-class type `B`. */
@deprecated("Use (a *: b *: c).as[CaseClass] instead of (a ~ b ~ c).gmap[CaseClass]", "0.6")
@deprecated("Use (a *: b *: c).to[CaseClass] instead of (a ~ b ~ c).gmap[CaseClass]", "0.6")
def gmap[B](implicit ev: Twiddler.Aux[B, A]): Decoder[B] =
map(ev.from)

Expand Down
2 changes: 1 addition & 1 deletion modules/core/shared/src/main/scala/Encoder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ trait Encoder[A] { outer =>
}

/** Adapt this `Encoder` from twiddle-list type A to isomorphic case-class type `B`. */
@deprecated("Use (a *: b *: c).as[CaseClass] instead of (a ~ b ~ c).gcontramap[CaseClass]", "0.6")
@deprecated("Use (a *: b *: c).to[CaseClass] instead of (a ~ b ~ c).gcontramap[CaseClass]", "0.6")
def gcontramap[B](implicit ev: Twiddler.Aux[B, A]): Encoder[B] =
contramap(ev.to)

Expand Down
8 changes: 4 additions & 4 deletions modules/core/shared/src/main/scala/Query.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ final case class Query[A, B](
def contramap[C](f: C => A): Query[C, B] =
dimap[C, B](f)(identity)

@deprecated("Use .contramapAs[CaseClass] instead of .gcontramap[CaseClass]", "0.6")
@deprecated("Use .contrato[CaseClass] instead of .gcontramap[CaseClass]", "0.6")
def gcontramap[C](implicit ev: Twiddler.Aux[C, A]): Query[C, B] =
contramap(ev.to)

def contramapAs[C](implicit ev: Iso[A, C]): Query[C, B] =
def contrato[C](implicit ev: Iso[A, C]): Query[C, B] =
contramap(ev.from)

/**
Expand All @@ -71,11 +71,11 @@ final case class Query[A, B](
def map[D](g: B => D): Query[A, D] =
dimap[A, D](identity)(g)

@deprecated("Use query(a *: b * :c).as[CaseClass] instead of query(a ~ b ~ c).gmap[CaseClass]", "0.6")
@deprecated("Use query(a *: b * :c).to[CaseClass] instead of query(a ~ b ~ c).gmap[CaseClass]", "0.6")
def gmap[D](implicit ev: Twiddler.Aux[D, B]): Query[A, D] =
map(ev.from)

def as[D](implicit ev: Iso[B, D]): Query[A, D] =
def to[D](implicit ev: Iso[B, D]): Query[A, D] =
map(ev.to)

def cacheKey: Statement.CacheKey =
Expand Down
4 changes: 2 additions & 2 deletions modules/docs/src/main/paradox/reference/Encoders.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ val person = (varchar *: int4).values.contramap((p: Person) => (p.name, p.age))
sql"INSERT INTO person (name, age) VALUES $person"
```

Because contramapping from case classes is so common, Skunk provides `as` which adapts
Because contramapping from case classes is so common, Skunk provides `to` which adapts
an encoder to a case class of the same structure.

```scala mdoc:invisible:reset
Expand All @@ -104,7 +104,7 @@ import skunk.codec.all._
```scala mdoc
case class Person(name: String, age: Int)

val person = (varchar *: int4).values.as[Person]
val person = (varchar *: int4).values.to[Person]

sql"INSERT INTO person (name, age) VALUES $person"
```
Expand Down
2 changes: 1 addition & 1 deletion modules/docs/src/main/paradox/reference/Fragments.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ val f9 = sql"INSERT ... VALUES ($varchar, $int4)"
val f10 = f9.contramap[Person](p => (p.name, p.age))

// alternatively
val f11 = f9.as[Person]
val f11 = f9.to[Person]
```


Expand Down
8 changes: 4 additions & 4 deletions modules/docs/src/main/paradox/reference/TwiddleLists.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,14 @@ twiddle: String *: Int *: Boolean *: org.typelevel.twiddles.EmptyTuple = Bob ::
bob2: Person = Person("Bob", 42, true)
```
`Decoder`s, `Encoder`s, and `Codec`s use this facility to provide `as`, which allows quick adaptation of a twiddle-list `Codec` (for instance) to one that maps to/from a case class.
`Decoder`s, `Encoder`s, and `Codec`s use this facility to provide `to`, which allows quick adaptation of a twiddle-list `Codec` (for instance) to one that maps to/from a case class.
```scala
@ val codec = varchar *: int4 *: bool
codec: Codec[String *: Int *: Boolean *: EmptyTuple] = Codec(varchar, int4, bool)
// Since `Person` has the same structure we can use `as` to create a `Codec[Person]`
@ val personCode = codec.as[Person]
// Since `Person` has the same structure we can use `to` to create a `Codec[Person]`
@ val personCode = codec.to[Person]
personCodec: Codec[Person] = Codec(varchar, int4, bool)
```
Expand Down Expand Up @@ -102,7 +102,7 @@ x match {
}
```
Skunk's `Codec`, `Decoder`, and `Encoder` types provided special methods for converting twiddle lists to case classes (`gimap`, `gmap`, `gcontramap` respectively). The `as` operation replaces all of these twiddle specific conversions.
Skunk's `Codec`, `Decoder`, and `Encoder` types provided special methods for converting twiddle lists to case classes (`gimap`, `gmap`, `gcontramap` respectively). The `to` operation replaces all of these twiddle specific conversions.
### Legacy Command Syntax
Expand Down
10 changes: 5 additions & 5 deletions modules/docs/src/main/paradox/tutorial/Command.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ val update2: Command[Info] =
.contramap { case Info(code, hos) => code *: hos *: EmptyTuple } // Command[Info]
```

However in this case the mapping is entirely mechanical. Similar to `as` on query results, we can skip the boilerplate and `as` directly to an isomosphic case class.
However in this case the mapping is entirely mechanical. Similar to `to` on query results, we can skip the boilerplate and `to` directly to an isomosphic case class.

```scala mdoc
val update3: Command[Info] =
Expand All @@ -120,7 +120,7 @@ val update3: Command[Info] =
SET headofstate = $varchar
WHERE code = ${bpchar(3)}
""".command // Command[String *: String *: EmptyTuple]
.as[Info] // Command[Info]
.to[Info] // Command[Info]
```

## List Parameters
Expand Down Expand Up @@ -217,19 +217,19 @@ object PetService {
private val insertOne: Command[Pet] =
sql"INSERT INTO pets VALUES ($varchar, $int2)"
.command
.as[Pet]
.to[Pet]

// command to insert a specific list of pets
private def insertMany(ps: List[Pet]): Command[ps.type] = {
val enc = (varchar *: int2).as[Pet].values.list(ps)
val enc = (varchar *: int2).to[Pet].values.list(ps)
sql"INSERT INTO pets VALUES $enc".command
}

// query to select all pets
private val all: Query[Void, Pet] =
sql"SELECT name, age FROM pets"
.query(varchar *: int2)
.as[Pet]
.to[Pet]

// construct a PetService
def fromSession[F[_]: Monad](s: Session[F]): PetService[F] =
Expand Down
12 changes: 6 additions & 6 deletions modules/docs/src/main/paradox/tutorial/Query.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,20 +110,20 @@ Because decoders are structural (i.e., they rely only on the position of column

### Mapping Decoder Results Generically

Because `Country` is a simple case class we can generate the mapping code mechanically. To do this, use `as` and specify the target data type.
Because `Country` is a simple case class we can generate the mapping code mechanically. To do this, use `to` and specify the target data type.

```scala mdoc
val country2: Decoder[Country] =
(varchar *: int4).as[Country]
(varchar *: int4).to[Country]
```

Even better, instead of constructing a named decoder you can `as` the `Query` itself.
Even better, instead of constructing a named decoder you can `to` the `Query` itself.

```scala mdoc
val c2: Query[Void, Country] =
sql"SELECT name, population FROM country"
.query(varchar *: int4)
.as[Country]
.to[Country]
```

## Parameterized Query
Expand Down Expand Up @@ -281,7 +281,7 @@ object QueryExample extends IOApp {
FROM country
WHERE name like $text
""".query(varchar *: bpchar(3) *: int4)
.as[Country]
.to[Country]

// run our simple query
def doSimple(s: Session[IO]): IO[Unit] =
Expand Down Expand Up @@ -356,7 +356,7 @@ object Service {
FROM country
WHERE name like $text
""".query(varchar *: bpchar(3) *: int4)
.as[Country]
.to[Country]

def fromSession[F[_]: Applicative](s: Session[F]): F[Service[F]] =
s.prepare(countries).map { pq =>
Expand Down
4 changes: 2 additions & 2 deletions modules/docs/src/main/paradox/tutorial/Transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,13 @@ object PetService {
private val insertOne: Command[Pet] =
sql"INSERT INTO pets VALUES ($varchar, $int2)"
.command
.as[Pet]
.to[Pet]

// query to select all pets
private val all: Query[Void, Pet] =
sql"SELECT name, age FROM pets"
.query(varchar *: int2)
.as[Pet]
.to[Pet]

// construct a PetService, preparing our statement once on construction
def fromSession(s: Session[IO]): IO[PetService[IO]] =
Expand Down
2 changes: 1 addition & 1 deletion modules/example/src/main/scala-2/Http4s.scala
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
// ): Resource[F, PooledCountries[F]] = {

// def countryQuery[A](where: Fragment[A]): Query[A, Country] =
// sql"SELECT code, name FROM country $where".query((bpchar(3) *: varchar).as[Country])
// sql"SELECT code, name FROM country $where".query((bpchar(3) *: varchar).to[Country])

// for {
// psAll <- sess.prepare(countryQuery(Fragment.empty))
Expand Down
2 changes: 1 addition & 1 deletion modules/example/src/main/scala/AppliedFragments.scala
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ object AppliedFragments extends IOApp {
}

case class Country(name: String, pop: Int, capital: Option[Int])
val country = (varchar *: int4 *: int4.opt).as[Country]
val country = (varchar *: int4 *: int4.opt).to[Country]

def topFive(s: Session[IO], name: Option[String], pop: Option[Int], capital: Option[Option[String]]): IO[Unit] =
for {
Expand Down
4 changes: 2 additions & 2 deletions modules/example/src/main/scala/Join.scala
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ object Join extends IOApp with StreamOps {
// A service implementation
object WorldService {

val pattern: Encoder[Pattern] = varchar.as[Pattern]
val pattern: Encoder[Pattern] = varchar.to[Pattern]

val countriesByNameQuery: Query[Pattern, ((String, String, Int), Option[City])] =
sql"""
Expand All @@ -46,7 +46,7 @@ object Join extends IOApp with StreamOps {
LEFT JOIN city ON city.countrycode = country.code
WHERE country.name LIKE $pattern
ORDER BY country.code, city.name ASC
""".query((varchar *: bpchar(3) *: int4).as[(String, String, Int)] ~ (varchar *: int4).as[City].opt)
""".query((varchar *: bpchar(3) *: int4).to[(String, String, Int)] ~ (varchar *: int4).to[City].opt)

def fromSession[F[_]](s: Session[F]): WorldService[F] =
new WorldService[F] {
Expand Down
2 changes: 1 addition & 1 deletion modules/example/src/main/scala/Main.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ object Main extends IOApp {
case class Country(name: String, code: String, indepyear: Option[Short], population: Int)

val country: Codec[Country] =
(varchar *: bpchar(3) *: int2.opt *: int4).as[Country]
(varchar *: bpchar(3) *: int2.opt *: int4).to[Country]

def anyLinesStdOut[F[_]: std.Console]: Pipe[F, Any, Unit] =
_.map(_.toString).printlns
Expand Down
2 changes: 1 addition & 1 deletion modules/example/src/main/scala/Minimal2.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ object Minimal2 extends IOApp {
from country
WHERE name like $varchar
""".query(bpchar(3) *: varchar *: int4)
.as[Country]
.to[Country]

def lookup[F[_]: Concurrent: Trace: Console](pat: String, s: Session[F]): F[Unit] =
Trace[F].span("lookup") {
Expand Down
2 changes: 1 addition & 1 deletion modules/example/src/main/scala/Minimal3.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ object Minimal3 extends IOApp {
from country
WHERE name like $varchar
""".query(bpchar(3) *: varchar *: int4)
.as[Country]
.to[Country]

def stream(pattern: String): Stream[IO, Country] =
for {
Expand Down
2 changes: 1 addition & 1 deletion modules/example/src/main/scala/Values.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ object Values extends IOApp {
case class Data(n: Int, s: String, b: Boolean)

val data: Codec[Data] =
(int4 *: bpchar *: bool).as[Data]
(int4 *: bpchar *: bool).to[Data]

// SQL depends on the number of `Data` elements we wish to "insert"
def query(len: Int): Query[List[Data], Data] =
Expand Down
2 changes: 1 addition & 1 deletion modules/tests/shared/src/test/scala/CommandTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ class CommandTest extends SkunkTest {
case class City(id: Int, name: String, code: String, district: String, pop: Int)

val city: Codec[City] =
(int4 *: varchar *: bpchar(3) *: varchar *: int4).as[City]
(int4 *: varchar *: bpchar(3) *: varchar *: int4).to[City]

val Garin = City(5000, "Garin", "ARG", "Escobar", 11405)
val Garin2 = City(5001, "Garin2", "ARG", "Escobar", 11405)
Expand Down
4 changes: 2 additions & 2 deletions modules/tests/shared/src/test/scala/QueryTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ class QueryTest extends SkunkTest {

sessionTest("as") { s =>
val f = sql"select $int4"
s.prepare(f.query(int4).as[Number]).flatMap { ps =>
s.prepare(f.query(int4).to[Number]).flatMap { ps =>
for {
n <- ps.unique(123)
_ <- assertEqual("123", n, Number(123))
Expand All @@ -93,7 +93,7 @@ class QueryTest extends SkunkTest {

sessionTest("gcontramap") { s =>
val f = sql"select $int4"
s.prepare(f.query(int4).contramapAs[Number]).flatMap { ps =>
s.prepare(f.query(int4).contrato[Number]).flatMap { ps =>
for {
n <- ps.unique(Number(123))
_ <- assertEqual("123", n, 123)
Expand Down
2 changes: 1 addition & 1 deletion modules/tests/shared/src/test/scala/codec/CodecTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ abstract class CodecTest(
}

sessionTest(s"${codec.types.mkString(", ")} (as)") { s =>
s.prepare(sqlString.query(codec.as[Box[A]])).flatMap { ps =>
s.prepare(sqlString.query(codec.to[Box[A]])).flatMap { ps =>
as.toList.traverse { a =>
for {
<- ps.unique(a)
Expand Down
Loading

0 comments on commit b6c63a7

Please sign in to comment.