2016-05-21 11 views
3

Ich lerne formlos, und zur Zeit Ich versuche, eine Funktion zu erstellen, die die folgenden: gegeben eine Art eines HList es die HList von None s zurückkehrt, mit der Option Typen entsprechend HList Typ.Deriving hList von Nullen aus einer Art hList von Monoide

Zum Beispiel:

create[String :: Int :: HNil] // returns None[String] :: None[Int] :: HNil 

So ist die Logik der folgende:

def create[A <: HList] { 
type HT = ??? //somehow getting Head type 
type TT = ??? //somehow getting Tail type 
// if HT is HNil HNil else Option.empty[HT] :: create[TT] 
} 

wie die Looks HT und TT kann durch IsHCons

def createHList[L <: HList](implicit ihc: IsHCons[L]): HList = { 
    type HT = ihc.H 
    type TT = ihc.T 
    // 
} 

zur Verfügung gestellt werden, aber dass steigt zwei Probleme

  1. Wie werden Typen verglichen?
  2. Compiler kann IsHCons[TT] für rekursiven Aufruf nicht finden. (Wie ISHCons[TT] von IsHCons[L] zu bekommen? Es ist nicht einmal möglich, HNil!)

Ich denke, dass ich um den (1) zu bekommen, von implicits für HNil und nicht HNil Bereitstellung, so dass der Compiler abholt das Recht implizit, abhängig vom Typ.

Bewege ich mich in die richtige Richtung?

Angesichts dessen, kann es sich lohnen, allgemeinere Frage zu stellen. Angesichts der HList von Monoids, ist es möglich, Null HList abzuleiten, bestehend aus Nullen von Monoiden geben?

Danke!

Antwort

6

Es ist ziemlich einfach Monoid Instanz für jeden HList zu definieren, wobei jedes Element Typ seine Monoid Instanz hat:

trait Monoid[T] { 
    def zero: T 
    def plus(t1: T, t2: T): T 
} 

object Monoid { 
    implicit val HNilMonoid: Monoid[HNil] = new Monoid[HNil] { 
    def zero = HNil 
    def plus(hn1: HNil, hn2: HNil) = HNil 
    } 
    implicit def HConsMonoid[H, T <: HList](implicit hm: Monoid[H], tm: Monoid[T]): Monoid[H :: T] = 
    new Monoid[H :: T] { 
     def zero = hm.zero :: tm.zero 
     def plus(ht1: H :: T, ht2: H :: T) = 
     hm.plus(ht1.head, ht2.head) :: tm.plus(ht1.tail, ht2.tail) 
    } 
} 

(tatsächlich, ich würde erwarten, formlos Lage sein, die oben automatisch ableiten, aber ich bin kein Experte für formlos)

Nimmt man nun an, dass wir Monoid[Int] und Monoid[String] an anderer Stelle definiert, können Sie einfach:

implicitly[Monoid[Int :: String :: HNil]].zero 

was genau Sie wollen, d. H. Eine HList von Nullen.

+0

Es gibt auch ein ähnliches [formloses Beispiel] (https://github.com/milessabin/shapeless/blob/master/examples/src/main/scala/shapeless/examples/monoids.scala), das "Monoid" ableitet. –

Verwandte Themen