我們可以通過無形創建一個文本類型的類型:得到一個「單型」
import shapeless.syntax.singleton._
var x = 42.narrow
// x: Int(42) = 42
但我怎麼能與Int(42)
操作的類型,如果它甚至不可能創造類型別名
type Answ = Int(42) // won't compile
// or
def doSmth(value: Int(42)) = ... // won't compile
我們可以通過無形創建一個文本類型的類型:得到一個「單型」
import shapeless.syntax.singleton._
var x = 42.narrow
// x: Int(42) = 42
但我怎麼能與Int(42)
操作的類型,如果它甚至不可能創造類型別名
type Answ = Int(42) // won't compile
// or
def doSmth(value: Int(42)) = ... // won't compile
1)Typelevel Scala你可以寫只是
val x: 42 = 42
type Answ = 42
def doSmth(value: 42) = ???
2)在Dotty的Sca你可以寫同樣的東西。
3)在Lightbend Scala(即標準的Scala)+無形可以編寫
import shapeless.Witness
import shapeless.syntax.singleton._
val x: Witness.`42`.T = 42.narrow
type Answ = Witness.`42`.T
def doSmth(value: Witness.`42`.T) = ???
在情況1)build.sbt應
scalaOrganization := "org.typelevel"
scalaVersion := "2.12.3-bin-typelevel-4"
scalacOptions += "-Yliteral-types"
在情況2)build.sbt應
scalaOrganization := "ch.epfl.lamp"
scalaVersion := "0.3.0-RC2"
和plugins.sbt
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.1.5")
在情況3)build.sbt應
scalaOrganization := "org.scala-lang"
scalaVersion := "2.12.3"
libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.2"
4),也可以在同一時間使用Typelevel Scala和無形。
Int(42)
不是類型的有效Scala的語法。
IIRC單類型是在scalac實施了一段時間,但程序員沒有定義這樣的語法。 Shapeless提供了宏,以及一些額外的機器。
特別地,shapeless.Witness
是同時包含類型信息和相關聯的值的對象,並且還可以從被召喚。
import shapeless.Witness
import shapeless.syntax.singleton._
import shapeless.test.illTyped // test string for causing type-errors when compiled
// --- Type aliases ---
val w = 42.witness
type Answ1 = w.T // that is your Int(42) singleton type
type Answ2 = Witness.`42`.T // same, but without extra variable
implicitly[Answ1 =:= Answ2] // compiles, types are the same
// --- Value definitions ---
val a: Answ1 = 42 // compiles, value OK, and no need to `narrow`
illTyped { "val b: Answ1 = 43" } // would not compile
val c: Witness.`43`.T = 43 // that syntax is OK here too
// --- Summoning values ---
val answ = Witness[Answ1].value // will not compile for non-singleton
def genericSingletonMethod[A](implicit W: Witness.Aux[A]) = s"Summoning ${W.value}"
assert { genericSingletonMethod[Answ1] == "Summoning 42" }
assert { genericSingletonMethod[Witness.`"string"`.T] == "Summoning string" }