假设我想在一些字符串和整数标识符之间进行映射,并且我希望我的类型使得无法获得运行时失败,因为有人试图查找超出范围的id.这是一个简单的API:
trait Vocab {
def getId(value: String): Option[Int]
def getValue(id: Int): Option[String]
}
Run Code Online (Sandbox Code Playgroud)
但是,如果用户通常会从中获取ID getId
并因此知道它们是有效的,那么这很烦人.以下是这种意义上的改进:
trait Vocab[Id] {
def getId(value: String): Option[Id]
def getValue(id: Id): String
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以这样:
class TagId private(val value: Int) extends AnyVal
object TagId {
val tagCount: Int = 100
def fromInt(id: Int): Option[TagId] =
if (id >= 0 && id < tagCount) Some(new TagId(id)) else None
}
Run Code Online (Sandbox Code Playgroud)
然后我们的用户可以使用Vocab[TagId]
而不必担心getValue
在典型情况下检查查找是否失败,但如果需要,他们仍然可以查找任意整数.但是,它仍然很尴尬,因为我们必须为每种我们想要词汇表的东西编写一个单独的类型.
我们也可以用精致的方式做这样的事情:
import eu.timepit.refined.api.Refined
import eu.timepit.refined.numeric.Interval.ClosedOpen
import shapeless.Witness
class Vocab(values: Vector[String]) { …
Run Code Online (Sandbox Code Playgroud) 问题:
我有一个案例类Passenger,从A点开始,到B点.
有效乘客意味着A点不等于B点.
Passenger(
a: Int,
b: Int
)
Run Code Online (Sandbox Code Playgroud)
题:
如何使用refind库设计Passenger类来达到目标?
我认为乘客应该采取两个或一个精炼类型的参数,如:
Passenger[A, B Refined NotEqual[A]](...)
Run Code Online (Sandbox Code Playgroud) 我正在使用NonEmptyString
精炼库中的类型。当连接两个字符串时,至少其中一个非空,结果显然是另一个非空字符串。但是有没有一种方法可以让 Scala 编译器相信这一事实,而不使用诸如 之类的不安全方法NonEmptyString.unsafeFrom
?
我正在试验它的一个库中提供的 scala 的精炼类型特性:
https://github.com/fthomas/refined
下面的代码代表一个简单的案例:
import eu.timepit.refined.auto._
import shapeless.{Witness => W}
type Vec5 = List[Int] Refined Size[Equal[W.`5`.T]]
val v1: Vec5 = List(1, 2, 3, 4, 5)
val v2: Vec5 = List(1 to 5: _*)
Run Code Online (Sandbox Code Playgroud)
尝试编译它时,我收到以下错误:
[Error] /home/peng/git/scalaspike/common/src/test/scala/com/tribbloids/spike/refined_spike/Example.scala:32: compile-time refinement only works with literals
[Error] /home/peng/git/scalaspike/common/src/test/scala/com/tribbloids/spike/refined_spike/Example.scala:34: compile-time refinement only works with literals
[Error] /home/peng/git/scalaspike/common/src/test/scala/com/tribbloids/spike/singleton_ops_spike/Example.scala:32: Cannot prove requirement Require[...]
three errors found
Run Code Online (Sandbox Code Playgroud)
应该注意的是,v1 和 v2 都可以在编译时轻松评估和内联,但是 Scala 编译器似乎拒绝这样做,并且对于List
type 似乎没有办法建议这一点。
那么这个功能怎么会有用呢?
我正在使用库https://github.com/fthomas/refined并希望转换java.util.UUID
为精炼的Uuid
.
如何转为java.util.UUID
精炼Uuid
?
更新
我有以下 http 路由:
private val httpRoutes: HttpRoutes[F] = HttpRoutes.of[F] {
case GET -> Root / UUIDVar(id) =>
program.read(id)
Run Code Online (Sandbox Code Playgroud)
读取函数定义如下:
def read(id: Uuid): F[User] =
query
.read(id)
.flatMap {
case Some(user) =>
Applicative[F].pure(user)
case None =>
ApplicativeError[F, UserError].raiseError[User](UserNotRegistered)
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨:
type mismatch;
[error] found : java.util.UUID
[error] required: eu.timepit.refined.string.Uuid
[error] program.read(id)
[error]
^
Run Code Online (Sandbox Code Playgroud)