Get type of a “singleton type”

后端 未结 2 887
醉酒成梦
醉酒成梦 2021-02-15 15:47

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 wit

相关标签:
2条回答
  • 2021-02-15 16:08

    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" }
    
    0 讨论(0)
  • 2021-02-15 16:27

    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.

    0 讨论(0)
提交回复
热议问题