Scala 基于类型的无形状Id生成器

Scala 基于类型的无形状Id生成器,scala,shapeless,hlist,Scala,Shapeless,Hlist,我想实现一个基于类型的id生成器,我可以这样调用它: val nextPersonId = idGen.id[Person] 我希望IdGen成为一种特质(如果可能): trait-IdGen[L好的,这是一个基于字符串的版本,它可能在许多角落的情况下存在bug,并且要求实现者以提供隐式类型标签的形式生成样板文件: import shapeless._ import scala.collection.mutable import scala.reflect.runtime.universe.

我想实现一个基于类型的id生成器,我可以这样调用它:

val nextPersonId = idGen.id[Person]
我希望IdGen成为一种特质(如果可能):


trait-IdGen[L好的,这是一个基于字符串的版本,它可能在许多角落的情况下存在bug,并且要求实现者以提供隐式类型标签的形式生成样板文件:

import shapeless._

import scala.collection.mutable
import scala.reflect.runtime.universe._

trait IdGen[L <: HList] {
  implicit val ltag: TypeTag[L]
  private val idGens = mutable.Map(typeTag[L].toString.split("""::\[""").toList.tail.map(_.split(""",shapeless""")(0) -> 0L): _*)

  def id[T: TypeTag] = {
    val t = typeOf[T].toString
    val id = idGens(t)
    idGens(t) = id + 1L
    id
  }
}

看到更好的实现将非常有趣。

我不确定您在这里要做什么。是否希望编译器为您增加ID?是否希望编译器仅强制使用某个ID生成器?如果您希望在运行时生成ID,则前者是不可能的,因为ID的数量太多生成的可能会根据控制流发生变化。根据您试图执行的操作,控制流可能不需要无形状。@badcook我将使用对L的typeTag的toString解析来写一个答案,希望它会变得更清晰:)
import shapeless._

import scala.collection.mutable
import scala.reflect.runtime.universe._

trait IdGen[L <: HList] {
  implicit val ltag: TypeTag[L]
  private val idGens = mutable.Map(typeTag[L].toString.split("""::\[""").toList.tail.map(_.split(""",shapeless""")(0) -> 0L): _*)

  def id[T: TypeTag] = {
    val t = typeOf[T].toString
    val id = idGens(t)
    idGens(t) = id + 1L
    id
  }
}
import java.util.NoSuchElementException

import org.junit.{Assert, Test}
import shapeless._

import reflect.runtime.universe._

class Person

class Booking

class Charge

class MyDao(implicit val ltag: TypeTag[Person :: Booking :: HNil]) extends IdGen[Person :: Booking :: HNil]

class Testy {
  val myDao = new MyDao

  @Test(expected = classOf[NoSuchElementException])
  def test {
    Assert.assertEquals(0L, myDao.id[Person])
    Assert.assertEquals(1L, myDao.id[Person])
    Assert.assertEquals(0L, myDao.id[Booking])
    myDao.id[Charge]
  }
}