繁体   English   中英

使用相同谓词进行细化时如何使用 Scala 的 Refined 库确保类型安全

[英]How to ensure type safety with Scala's Refined library when using the same predicate for refinement

我是 scala 和精炼库的新手,但我正在尝试基于 UUID 创建两种精炼类型。

为此,我这样做了(注意:本例中的 Uuid 来自 eu.timepit.refined.string.Uuid):

type UuidPredicate = Uuid

type UuidA = String Refined UuidPredicate
type UuidB = String Refined UuidPredicate

但是,这似乎只创建别名,因此没有类型安全性。

因此,如果我有一个像Product(a UuidA, b UuidB)这样的构造函数并继续执行以下操作:

val myUuid: UuidA = "9f9ef0c6-b6f8-11ea-b3de-0242ac130004"
val Product = Product(myUuid, myUuid)

它将正确编译和运行。 有没有办法确保不是这种情况? 如果一个变量被创建为一种类型,我怎样才能使它只用作那个特定的细化类型,即使类型基本相同?

最简单的就是引入不同的数据类型

case class UuidA(value: String Refined UuidPredicate)
case class UuidB(value: String Refined UuidPredicate)

你不能让UuidAUuidB扩展AnyVal因为Refined已经扩展AnyVal并且 Scala 不允许嵌套值类。

如果您希望避免使用UuidA包装的运行时开销, UuidB您可以尝试@newtype正如@LuisMiguelMejíaSuárez建议的那样

import io.estatico.newtype.macros.newtype

@newtype case class UuidA(value: String Refined UuidPredicate)
@newtype case class UuidB(value: String Refined UuidPredicate)

或者尝试添加更多标签

import eu.timepit.refined.api.Refined
import eu.timepit.refined.string.Uuid
import eu.timepit.refined.auto._
import shapeless.tag
import shapeless.tag.@@

type UuidPredicate = Uuid
type UuidString = Refined[String, UuidPredicate]
type TagA
type TagB
type UuidA = UuidString @@ TagA
type UuidB = UuidString @@ TagB

case class Product(a: UuidA, b: UuidB)
val myUuid: UuidA = tag[TagA][UuidString]("9f9ef0c6-b6f8-11ea-b3de-0242ac130004")
//  val product = Product(myUuid, myUuid) // doesn't compile
val myUuid1: UuidB = tag[TagB][UuidString]("9f9ef0c6-b6f8-11ea-b3de-0242ac130004")
val product1 = Product(myUuid, myUuid1) // compiles

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM