问题
I have two shapeless extensible records, person
and employee
. The employee
record is a subtype of person
in some sense because it has all of the fields that person
does and those fields are all subtypes of the corresponding fields in person
:
import shapeless._ ; import syntax.singleton._ ; import record._
val employeeId = ("first name" ->> "Jane") :: ("last name" ->> "Doe") :: ("title" ->> "software engineer") :: HNil
val employee =
("id" ->> employeeId) ::
("city" ->> "San Francisco") ::
("company" ->> "Generic Inc.") ::
HNil
val personId = ("first name" ->> "Jane") :: ("last name" ->> "Doe") :: HNil
val person =
("id" ->> personId) ::
("city" ->> "San Francisco") ::
HNil
How can I check if one record is a subtype of another? I want to be able to do this both at compile time and at runtime. One use-case I have in mind is that I want to statically verify that a function doesn't remove any fields from a record. So my function could take a person
and transform it into an employee
but if it dropped the "city" or "id" fields the program should not compile.
I also want to be able to compare the shared components of employee
and person
. I want to view both objects as just person
s and check them for equality. How can I do this?
回答1:
- How can I check if one record is a subtype of another?
You may look at the Extractor type class in this repo. It implements both depth and width subtyping.
https://github.com/eugengarkusha/RecordsDeepMerge
- I want to be able to do this both at compile time and at runtime
Subtyping relation is witnessed in compile time. Use the Extractor type class(from mentioned repo) to get all fields of super-record from sub-record.
- I also want to be able to compare the shared components of employee and person. I want to view both objects as just persons and check them for equality. How can I do this?
(using the code from mentioned repo):
type PersonId = Record.`"first name" ->String, "last name" ->String`.T
type Person = Record.`"id" -> PersonId, "city" -> String`.T
employee1.deepExtract[Person] == employee2.deepExtract[Person]
- I want to statically verify that a function doesn't remove any fields from a record. So my function could take a person and transform it into an employee but if it dropped the "city" or "id" fields the program should not compile.
no subtype checks are needed in this case:
def personToEmployee(p: Person): Employee = ???
type checker won't let you remove city or id fields
来源:https://stackoverflow.com/questions/32803930/checking-for-subtype-relationship-between-extensible-records-in-shapeless