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.
-
Type members
-
FieldTypes
- Type of label-value pairs as a tuple type or a structural type
-
ElemLabels
- Type of field labels as a tuple type
-
ElemTypes
- Type of field values as a tuple type
-
-
Method
-
iterableOf(r: R): Iterable[(String, Any)]
- Retrieve label-value pairs from the conversion target of type
R
- Retrieve label-value pairs from the conversion target of type
-
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))