【问题标题】:Get type of a "singleton type"获取“单例类型”的类型
【发布时间】:2018-02-21 05:44:23
【问题描述】:

我们可以通过 shapeless 创建文字类型:

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

【问题讨论】:

    标签: scala generic-programming shapeless


    【解决方案1】:

    1) 在Typelevel Scala 你可以只写

    val x: 42 = 42
    
    type Answ = 42
    
    def doSmth(value: 42) = ???
    

    2) 在Dotty Scala 中,您可以编写相同的代码。

    3) 在 Lightbend Scala(即标准 Scala)+ Shapeless 中,您可以编写

    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 和 Shapeless。

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        猜你喜欢
        • 2019-01-20
        • 2020-07-23
        • 2021-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-11-08
        • 1970-01-01
        相关资源
        最近更新 更多