36 votes

Intersection de multiples conversions implicites: réinventer la roue?

Bon, juste attention: ceci est un suivi à ma question ridicule de la semaine dernière. Bien que je pense que cette question n'est pas aussi ridicule. De toute façon, va ici:

Précédente question ridicule:

Supposons que j'ai une certaine base trait T avec des sous-classes A, B et C, je peux déclarer une collection Seq[T] par exemple, qui peuvent contenir des valeurs de type A, B et C. Faire de la sous-typage plus explicite, nous allons utiliser l' Seq[_ <: T] type lié à la syntaxe.

Maintenant, au lieu d'assumer, j'ai un typeclass TC[_] avec les membres de l' A, B et C (où "membre" signifie que le compilateur peut trouver quelques - TC[A], etc. dans l'étendue implicite). Comme ci-dessus, je veux déclarer une collection de type Seq[_ : TC], à l'aide de contexte lié à la syntaxe.

Ce n'est pas légal Scala, et d'essayer d'émuler peut vous faire sentir comme une mauvaise personne. Se rappeler que le contexte lié à la syntaxe (lorsqu'il est utilisé correctement!) desugars dans un paramètre implicite de la liste pour la classe ou la méthode en cours de définition, qui n'a pas de sens ici.

Nouveau site:

Supposons donc que typeclass cas (c'est à dire des valeurs implicites) sont hors de question, et au lieu de cela, nous devons utiliser les conversions implicites dans ce cas. J'ai un certain type V (le "v" est censé représenter "point de vue" fwiw), et les conversions implicites dans le champ d'application A => V, B => V et C => V. Maintenant, je peux remplir un Seq[V], malgré A, B et C étant pas liés.

Mais que faire si je veux une collection de choses qui sont implicitement convertible à la fois à des vues en V1 et V2? Je ne peux pas dire Seq[V1 with V2] parce que mon conversions implicites ne sont pas comme par magie globale de cette façon.

Intersection de conversions implicites?

J'ai résolu mon problème comme ceci:

// a sort of product or intersection, basically identical to Tuple2
final class &[A, B](val a: A, val b: B)

// implicit conversions from the product to its member types
implicit def productToA[A, B](ab: A & B): A = ab.a
implicit def productToB[A, B](ab: A & B): B = ab.b

// implicit conversion from A to (V1 & V2)
implicit def viewsToProduct[A, V1, V2](a: A)(implicit v1: A => V1, v2: A => V2) =
  new &(v1(a), v2(a))

Maintenant, je peux écrire Seq[V1 & V2] comme un boss. Par exemple:

trait Foo { def foo: String }
trait Bar { def bar: String }

implicit def stringFoo(a: String) = new Foo { def foo = a + " sf" }
implicit def stringBar(a: String) = new Bar { def bar = a + " sb" }
implicit def intFoo(a: Int) = new Foo { def foo = a.toString + " if" }
implicit def intBar(a: Int) = new Bar { def bar = a.toString + " ib" }

val s1 = Seq[Foo & Bar]("hoho", 1)
val s2 = s1 flatMap (ab => Seq(ab.foo, ab.bar))
// equal to Seq("hoho sf", "hoho sb", "1 if", "1 ib")

Les conversions implicites de String et Int type Foo & Bar se produisent lorsque la séquence est rempli, et ensuite les conversions implicites de Foo & Bar de Foo et Bar se produisent lors de l'appel d' foobar.foo et foobar.bar.

L'actuelle question ridicule(s):

  1. Personne n'a mis en œuvre ce modèle n'importe où avant, ou suis-je le premier idiot pour le faire?
  2. Est-il un moyen beaucoup plus simple de faire ce que j'ai aveuglément manqué?
  3. Si non, alors comment pourrais-je les mettre en œuvre plus générale, de plomberie, de telle sorte que je peux écrire Seq[Foo & Bar & Baz]? Cela semble comme un travail pour HList...
  4. Extra mega bonus de combo: dans la mise en œuvre le plus de la plomberie générale, puis-je contraindre les types uniques? Par exemple, j'aimerais interdire Seq[Foo & Foo].

L'annexe de l'échec:

Ma dernière tentative (gist). Pas terrible, mais il ya deux choses que je n'aime pas il y a:

  • L' Seq[All[A :: B :: C :: HNil]] de la syntaxe (je veux l' HList trucs pour être opaque, et préférez Seq[A & B & C])
  • L'annotation de type explicite (abc[A].a) nécessaire à la conversion. Il semble que vous pouvez avoir le type d'inférence ou de conversions implicites, mais pas les deux... je ne pouvais pas comprendre comment l'éviter, de toute façon.

1voto

Edmondo1984 Points 5059

Je peux donner une réponse partielle au point 4. Ceci peut être obtenu en appliquant une technique telle que:

http://vpatryshev.blogspot.com/2012/03/miles-sabins-type-negation-in-practice.html

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X