Checking for subtype relationship between extensible records in shapeless

自闭症网瘾萝莉.ら 提交于 2020-01-02 07:32:09

问题


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 persons 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!