如何提前指定无形单例类型
How to specify a shapeless singleton type ahead of time
我想构造一个类似 LimitedString[Limit]
的类型,其中 Limit
是字符串最大长度的类型表示。
它将按照
的方式工作
class LimitedString[Limit] [private](val s: String)
object LimitedString {
private def getLimit[Limit]: Int = ??? // turn `Limit` type into a value
def truncate[Limit](s: String) = new LimitedString[Limit](s take getLimit)
def get[Limit](s: String) =
if(s.length < getLimit) Some(new LimitedString[Limit](s))
else None
}
type Str100 = LimitedString[100] // obviously this won't work
def someLibraryMethod(s: Str100) = { ... }
我不知道如何实际键入(如在键盘中)Limit
的类型(如在编译中)。
我开始研究 Shapeless 的单例类型,发现你可以说
100.narrow
// res1: Int(100) = 100
但是如果我尝试使用 Int(100)
作为类型,我会得到错误。
val x: Int(100) = 100
// error: ';' expected but '(' found.
此外,我将如何实现类似 def getLimit[Limit]: Int
的东西?
我采纳了@TravisBrown 的建议来研究 Shapless 的 Witness
,并得出了这个结论:
class LimitedString[Limit <: Int] private[util](val s: String) extends AnyVal {
override def toString = s
}
class LimitedStringCompanion[Limit <: Int : Witness.Aux]{
def limit: Int = implicitly[Witness.Aux[Limit]].value
def unapply(s: String): Option[LimitedString[Limit]] = {
if(s.length > limit) None else Some(new LimitedString(s))
}
def truncate(s: String): LimitedString[Limit] = new LimitedString(s take limit)
}
用法:
import shapeless._
object MyLibraryThing {
type Name = LimitedString[Witness.`50`.T]
object Name extends LimitedStringCompanion[Witness.`50`.T]
def rename(id: Int, name: Name) = { ... }
}
让它发挥作用的关键因素:
Witness.Aux
是一个类型类,您可以使用它来让单例 value
退出类型
- 单例类型
Witness.`50`.T
实际上是Int
的子类型
- 类型别名使交互更方便
我想构造一个类似 LimitedString[Limit]
的类型,其中 Limit
是字符串最大长度的类型表示。
它将按照
的方式工作class LimitedString[Limit] [private](val s: String)
object LimitedString {
private def getLimit[Limit]: Int = ??? // turn `Limit` type into a value
def truncate[Limit](s: String) = new LimitedString[Limit](s take getLimit)
def get[Limit](s: String) =
if(s.length < getLimit) Some(new LimitedString[Limit](s))
else None
}
type Str100 = LimitedString[100] // obviously this won't work
def someLibraryMethod(s: Str100) = { ... }
我不知道如何实际键入(如在键盘中)Limit
的类型(如在编译中)。
我开始研究 Shapeless 的单例类型,发现你可以说
100.narrow
// res1: Int(100) = 100
但是如果我尝试使用 Int(100)
作为类型,我会得到错误。
val x: Int(100) = 100
// error: ';' expected but '(' found.
此外,我将如何实现类似 def getLimit[Limit]: Int
的东西?
我采纳了@TravisBrown 的建议来研究 Shapless 的 Witness
,并得出了这个结论:
class LimitedString[Limit <: Int] private[util](val s: String) extends AnyVal {
override def toString = s
}
class LimitedStringCompanion[Limit <: Int : Witness.Aux]{
def limit: Int = implicitly[Witness.Aux[Limit]].value
def unapply(s: String): Option[LimitedString[Limit]] = {
if(s.length > limit) None else Some(new LimitedString(s))
}
def truncate(s: String): LimitedString[Limit] = new LimitedString(s take limit)
}
用法:
import shapeless._
object MyLibraryThing {
type Name = LimitedString[Witness.`50`.T]
object Name extends LimitedStringCompanion[Witness.`50`.T]
def rename(id: Int, name: Name) = { ... }
}
让它发挥作用的关键因素:
Witness.Aux
是一个类型类,您可以使用它来让单例value
退出类型- 单例类型
Witness.`50`.T
实际上是Int
的子类型
- 类型别名使交互更方便