record4s

Defining Your Own Conversions

Converting records to/from Products is described in Conversions section. You can also define conversions for any other types.

As an example, we use the following Person class as the target of conversions.

class Person(val name: String, val age: Int) {
  override def toString: String = s"Person(${name} (${age}))"
}

Making this class a case class is the easiest way to achieve the conversions but we will define conversions by hand for exercise without making it a case class.

RecordLike

Giving a RecordLike instance for a type enables the type to be converted to a record. RecordLike consists of type members and a method to retrieve fields as an iterable.

A RecordLike instance for Person class can be given as the following.

import com.github.tarao.record4s.RecordLike

given RecordLike[Person] with
  type FieldTypes = (("name", String), ("age", Int))
  type ElemLabels = ("name", "age")
  type ElemTypes = (String, Int)

  def iterableOf(p: Person): Iterable[(String, Any)] =
    Seq(("name", p.name), ("age", p.age))

Then, Record.from works for a Person instance.

import com.github.tarao.record4s.Record

Record.from(Person("tarao", 3))
// res0: % {
//   val name: String
//   val age: Int
// } = %(name = tarao, age = 3)

It is also possible to use a Person as a right-hand-side argument of concatenation.

%(email = "tarao@example.com") ++ Person("tarao", 3)
// res1: % {
//   val email: String
//   val name: String
//   val age: Int
// } = %(email = tarao@example.com, name = tarao, age = 3)

More complicated example can be found in the source code of RecordLike.

Converter

Giving a Converter instance for a type enables the type to be converted from a record. Converter is simply an interface with apply: From => To. Convert for Person class can be given as the following.

import com.github.tarao.record4s.Converter

type PersonRecord = % { val name: String; val age: Int }

given [R <: PersonRecord]: Converter[R, Person] with
  def apply(record: R): Person =
    Person(record.name, record.age)

Then, to[Person] on a record converts the record to a Person.

%(name = "tarao", age = 3).to[Person]
// res2: Person = Person(tarao (3))