在我的代码库中,我使用标签将一些信息编码为类型。由于标签使用t.asInstanceOf[T @@ U]
,我可以通过在包装和未包装的值之间编写映射来解决许多麻烦。
最近我用标记类型打了墙,因为它们打破了我想要使用的无形状的一些功能,所以我试图使用值类。
到目前为止,我可以欺骗一些例如使用类似以下内容的布尔检查标记类型:
implicit class TaggedBooleanAsFirstOperand[P1, U](val c: Rep[P1 @@ U]) {
private val em = new BooleanColumnExtensionMethods[P1](c.asInstanceOf[Rep[P1]])
type o = OptionMapperDSL.arg[Boolean, P1]
def @&&[P2, R](b: Rep[P2])(implicit om: o#arg[Boolean, P2]#to[Boolean, R]): Rep[R] = em.&&[P2, R](b)
def @||[P2, R](b: Rep[P2])(implicit om: o#arg[Boolean, P2]#to[Boolean, R]): Rep[R] = em.||[P2, R](b)
def unary_! : Rep[P1] = em.unary_!
}
implicit class TaggedBooleanAsSecondOperand[P1](val c: Rep[P1]) {
private val em = new BooleanColumnExtensionMethods[P1](c)
type o = OptionMapperDSL.arg[Boolean, P1]
def &&@[P2, U, R](b: Rep[P2 @@ U])(implicit om: o#arg[Boolean, P2]#to[Boolean, R]): Rep[R] = em.&&[P2, R](b.asInstanceOf[Rep[P2]])
def ||@[P2, U, R](b: Rep[P2 @@ U])(implicit om: o#arg[Boolean, P2]#to[Boolean, R]): Rep[R] = em.||[P2, R](b.asInstanceOf[Rep[P2]])
}
implicit class TaggedBooleanAsBothOperands[P1, U](val c: Rep[P1 @@ U]) {
private val em = new BooleanColumnExtensionMethods[P1](c.asInstanceOf[Rep[P1]])
type o = OptionMapperDSL.arg[Boolean, P1]
def @&&@[P2, V, R](b: Rep[P2 @@ V])(implicit om: o#arg[Boolean, P2]#to[Boolean, R]): Rep[R] = em.&&[P2, R](b.asInstanceOf[Rep[P2]])
def @||@[P2, V, R](b: Rep[P2 @@ V])(implicit om: o#arg[Boolean, P2]#to[Boolean, R]): Rep[R] = em.||[P2, R](b.asInstanceOf[Rep[P2]])
}
然而,对于AnyVal
,我不能简单地将一种类型转换为我想要的另一种类型,而且我必须提供一些可以实现我想要的诚实代码。
我试着阅读Slick源代码,但是我应该从哪里开始的整个想法对我来说有点模糊 - 相关信息分布在很多地方,所以我不能简单地指出一些地方,例如想象一下如何将一个Rep
映射到另一个{0}或从包装和展开的布尔中提取数据并将它们组合起来。
一些Slick专家可以为那些推荐一些好的起点吗?
答案 0 :(得分:0)
标签实际上不仅为您提供类型安全。它也为您提供抽象级别。将boolean
包装到tag
后,您将从布尔值的运行时表示中抽象出来。顺便说一下,您应该使用Tag.unwrap
或Tag.unsubst
代替asInstanceOf
。
Slick适用于较低级别的抽象。它适用于SQL所知道的简单类型。
当然,在使用DB之前,您需要在其间的某处使用unwrap
标签。
我会将它封装在表模式中。请参阅映射表部分:http://slick.lightbend.com/doc/3.0.0/schemas.html