Get type of a “singleton type”

橙三吉。 提交于 2020-08-22 05:21:30

问题


We can create a literal types via shapeless:

import shapeless.syntax.singleton._
var x = 42.narrow
// x: Int(42) = 42

But how can I operate with Int(42) as a type if it's even impossible to create type alias

type Answ = Int(42) // won't compile
// or
def doSmth(value: Int(42)) = ... // won't compile

回答1:


1) In Typelevel Scala you can write just

val x: 42 = 42

type Answ = 42

def doSmth(value: 42) = ???

2) In Dotty Scala you can write the same.

3) In Lightbend Scala (i.e. standard Scala) + Shapeless you can write

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) = ???

In case 1) build.sbt should be

scalaOrganization := "org.typelevel"
scalaVersion := "2.12.3-bin-typelevel-4"
scalacOptions += "-Yliteral-types"

In case 2) build.sbt should be

scalaOrganization := "ch.epfl.lamp"
scalaVersion := "0.3.0-RC2"

and plugins.sbt

addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % "0.1.5")

In case 3) build.sbt should be

scalaOrganization := "org.scala-lang"
scalaVersion := "2.12.3"
libraryDependencies += "com.chuusai" %% "shapeless" % "2.3.2"

4) or you can use Typelevel Scala and Shapeless at the same time.




回答2:


Int(42) is not a valid Scala syntax for type.

IIRC singleton types were implemented in scalac for a while, but programmers had no syntax of defining such. Shapeless provides that, with macros, as well as some extra machinery.

In particular, shapeless.Witness is an object that contains both type information and associated value, and also can be summoned from either.

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" }


来源:https://stackoverflow.com/questions/46181854/get-type-of-a-singleton-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!