以类似HList的样式生成嵌套数据结构

时间:2017-02-23 00:15:27

标签: scala types nested shapeless

假设:

val a = "foo" :: "bar" :: MyNil[Float]()

我希望a.ArrayType解析为Array[Array[Float]]a.toList生成Seq("foo", "bar")。对于较长的列表,a.ArrayType应该嵌套得更深,但叶子类型应该保持不变。

我正在尝试定义一个允许上述内容的数据结构,但到目前为止我的尝试失败了。

我有一些方法都不能完全发挥作用。要么我没有得到诱导步骤,要么感应开始。也许有一些无形的解决方案让我看不到?这是我到目前为止我没有得到感应开始的原因:

trait NestedArrays[A] {
  type BaseType = A
  type ArrayType <: Array[_]
  val name: String
  val t: NestedArrays[A]

  def ::(name: String): ::[A] = new ::(name, this)

  def toList: List[String] = name :: t.toList
}

case class ::[A](name: String, t: NestedArrays[A]) extends NestedArrays[A] {
  override type BaseType = t.BaseType
  override type ArrayType = Array[t.ArrayType]
}

class HANil[A] extends NestedArrays[A] {
  override type BaseType = A
  override type ArrayType = A

  override val t: NestedArrays[A] = null
  override val name: String = null

  override def toList: List[String] = Nil
}

object HANil {
  def apply[A](): NestedArrays[A] = new HANil[A]

  // val test = "bar" :: "baz" :: "foo" :: begin[Float]("bal")
  val test = "foo" :: "bar" :: HANil[Float]()
  //val test = begin[Float]("boo")
  val a = Array.ofDim[Float](2, 2).asInstanceOf[test.ArrayType]
}

我的其他解决方案是否ArrayType必须是数组(如果没有,导入步骤失败,但开始工作),或者NestedArrays是否有类型参数,但是这都是细节工作。我对其他方法的其他任何解决方案都很满意,虽然我想我需要在所有解决方案中进行一些依赖于路径的输入。也许一些隐含的参数可以指导我的方式?

1 个答案:

答案 0 :(得分:1)

我是否正确观察到列表中只包含String类型的元素,您只需附加要用于参数化嵌套数组的“类型标记”(Float)?所以你真的没有HList,但你只使用“HList”来计算嵌套级别?

以下代码可用于通过调用step函数来构建嵌套数组。添加名称应该是微不足道的。

scalafiddle.io

trait I {
  type Out
  def step: I.Aux[Array[Out]] = I[Array[Out]]
  def create(x: Any): Out = x.asInstanceOf[Out]
}

object I {
  type Aux[X] = I {type Out = X}
  def apply[A]: Aux[A] = new I {type Out = A}
}

val x: Float = I[Float].create(1)

val ax: Array[Float] = I[Float].step.create(Array(0.1f))

val aax: Array[Array[Float]] = I[Float].step.step.create(Array(Array(0.1f)))

//The following fail to compile

//val aax2: Array[Array[Float]] = I[Float].step.create(Array(0.1f))
//val aax3: Array[Float] = I[Float].step.step.create(Array(0.1f))