2012-02-12 3 views
3

En jouant avec shapeless nombres naturels dans l'excitation, je me demande quelle pourrait être la meilleure approche pour obtenir la valeur entière de par exemple. un produit de nats.Int valeur de Prod in shapeless

Extrait de shapeless nat.scala:

trait Prod[A <: Nat, B <: Nat] { 
    type Out <: Nat 
} 

trait ProdAux[A <: Nat, B <: Nat, C <: Nat] 

object Prod { 
    implicit def prod[A <: Nat, B <: Nat, C <: Nat](implicit diff : ProdAux[A, B, C]) = new Prod[A, B] { 
    type Out = C 
    } 
} 

object ProdAux { 
    import Nat._0 

    implicit def prod1[B <: Nat] = new ProdAux[_0, B, _0] {} 
    implicit def prod2[A <: Nat, B <: Nat, C <: Nat, D <: Nat] 
    (implicit ev1 : ProdAux[A, B, C], ev2 : SumAux[B, C, D]) = new ProdAux[Succ[A], B, D] {} 
} 

Je suis Jusqu'à présent, viens avec la définition simple de

def toInt[A <: Nat, B <: Nat, C <: Nat](p: Prod[A, B]) 
    (implicit paux: ProdAux[A, B, C], iv: ToInt[C]): Int = iv() 

En fait, cette approche nécessiterait des implémentations quelque peu redondantes du code équivalent pour par exemple des sommes, des diffs, des factorielles etc. Donc je préfère être en mesure d'utiliser la méthode "par défaut" toInt[A <: Nat].

Comment le feriez-vous? Et est-il possible d'utiliser les types internes (Prod#Out, Sum#Out, ...)?

Répondre

2

Désolé, j'ai raté cette question plus tôt (BTW, le shapeless mailing list est un bon endroit pour poser ce genre de question).

Je pense que vous avez un peu mal compris le rôle de la classe de type Prod: ses instances ne sont pas eux-mêmes Nat s, ils sont témoins d'une relation entre trois tenant Nat s, à savoir que (A * B) == C. En tant que tel, il ne fait pas vraiment tout son sens pour convertir Prod instances en Int s. Ou plutôt, si c'était le cas, il serait tout aussi logique que la valeur résultante corresponde à l'une des A, B ou C, ou au triple de chacun d'entre eux.

Pour être utilisés comme termes de preuve dans les définitions de méthodes, le style que vous avez affiché est à peu près comme prévu ... voir here pour un exemple. Clairement cependant, cela ne fonctionne pas très bien pour jouer avec des choses sur le REPL. Pour cela un peu plus lisse vous pouvez essayer des choses le long des lignes de,

def prod[A <: Nat, B <: Nat](implicit prod : Prod[A, B]) = 
    new { def toInt(implicit ti : ToInt[prod.Out]) = ti() } 

qui permet des interactions REPL comme,

scala> prod[_2, _3].toInt 
res0: Int = 6 

Si cela est encore pas tout à fait ce que vous êtes après alors s'il vous plaît la tête sur la liste de diffusion et esquisser ce que vous aimeriez pouvoir faire.

+0

Miles, merci beaucoup! En fait, j'ai bien compris la classe de type 'Prod' mais j'aurais dû le préciser plus clairement dans mon OP. Votre réponse est exactement ce que je cherchais! – fotNelton