2017-02-23 1 views
2

Gegeben:Generieren von verschachtelten Datenstrukturen in einem hList-Stil

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

Ich möchte, dass a.ArrayType-Array[Array[Float]] löst, sowie a.toListSeq("foo", "bar") erzeugt. Für eine längere Liste sollte die a.ArrayType tiefer geschachtelt werden, aber der Blatttyp sollte gleich bleiben.

Ich versuche eine Datenstruktur zu definieren, die das obige ermöglicht, aber mit meinen eigenen Versuchen bisher fehlgeschlagen ist.

Ich habe einige Ansätze, die alle nicht vollständig funktionieren. Entweder bekomme ich den Induktionsschritt oder den Induktionsstart nicht. Vielleicht gibt es eine formlos-aktivierte Lösung, die ich nicht sehe? Das ist, was ich habe, so weit, wo ich nicht die Induktion Start bekommen:

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

Meine anderen Lösungen variieren um, ob ArrayType ein Array sein muss oder nicht (wenn nicht, wird der Induktionsschritt ausfällt, aber der Start works) oder ob NestedArrays einen Typparameter hat oder nicht, aber es ist alles Detailarbeit. Ich würde mich über jede andere Lösung auch mit anderen Ansätzen freuen, obwohl ich denke, dass ich bei allen Lösungen ein pfadabhängiges Tippen benötige. Vielleicht können einige implizite Parameter meinen Weg weisen?

+0

Muss ich beobachten richtig, dass die Listenelemente von nur Typ 'String' enthält, und Sie einfach ein„Typenschild“(' float') anhängen, die Sie verwenden möchten Ihre verschachtelte zu parametrieren 'Array'? Sie haben also nicht wirklich eine 'HList', aber Sie verwenden die' 'HList'' nur, um die Verschachtelungsebene zu zählen? – ziggystar

+0

Korrekt. Je mehr Elemente in der Liste enthalten sind, desto mehr Verschachtelung möchte ich haben. Es ist kein formloses 'HList', ich dachte nur, es könnte eine 'HList'-basierte Magie geben, die ich buchstabieren könnte. Für ein wenig mehr Kontext: Ich habe eine typsichere Schicht um eine javaish API erstellen möchten, um Arrays Gießen erfordert, dass multidimensionalen Arrays haben können, sind die Namen die Namen der Koordinatenachsen verwendet, um die Daten zu beschreiben. –

+0

Vielen Dank für Ihre Anfrage in http://stackoverflow.com/questions/42410653/is-there-infrastructure-in-shapeless-that-takes-a-type-constructor-to-the-power über formlos :) –

Antwort

1

Ich beobachte korrekt, dass die Liste Elemente nur des Typs String enthält, und Sie fügen einfach einen "type tag" (Float) an, den Sie verwenden möchten, um Ihr verschachteltes Array zu parametrisieren? Sie haben also nicht wirklich eine HList, aber Sie verwenden die "HList" nur, um die Verschachtelungsebene zu zählen?

Der folgende Code kann zum Erstellen verschachtelter Arrays verwendet werden, indem eine step-Funktion aufgerufen wird. Das Hinzufügen der Namen sollte trivial sein.

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)) 
+0

Got Es funktioniert mit Ihrem Ansatz, vielen Dank –

Verwandte Themen