Dopo aver esaminato alcuni esempi di tipi con maggiore scalabilità Scala nel tutorial this, ho iniziato a giocare con (a) impliciti e (b) tecniche per scrivere metodi che gestiscono genericamente sottoclassi di un tratto che è definito come un livello superiore. tipo gentilitato. Ho già avuto una grande risposta in (b) here che mi si sta avvicinando alla soluzione del problema di seguito:L'ambiguità implicita di Scala non viene risolta senza fastidioso argomento fittizio per contrassegnare il tipo.
voglio creare una fabbrica per la creazione di contenitori Singleton (Set, liste, array) che avvolgono l'elemento che Passo alla funzione di fabbrica. [Anche se esiste già una libreria Scala , lo faccio come un esercizio di apprendimento. Ma, hey ... se ce n'è uno, per favore fatemelo sapere]
Il risultato finale dovrebbe mi permetta di fare questo:!
scala> var j: Set[String] = wrapItemInContainer("foo")
j: Set[String] = Set(foo)
scala> var k: List[Int] = wrapItemInContainer(9)
k: List[Int] = List(9)
La soluzione mi è venuto in mente è illustrato di seguito. Devo fornire un fastidioso argomento finale fittizio in modo che possa aiutare il compilatore a capire che tipo di contenitore voglio. Funziona, ma sono sconcertato dal fatto che la firma del tipo della variabile che voglio assegnare il risultato a (j, k..etc.) Non dia al compilatore informazioni sufficienti per capire quale ContainerFactory è implicitamente definito deve essere usato
Questa soluzione goffa funziona:
trait ContainerFactory[M[_]] { def put[A](x: A): M[A] }
implicit val factory = new ContainerFactory[List] { def put[A](x: A) = List(x) } // factory for List containers
implicit val factory2 = new ContainerFactory[Set] { def put[A](x: A) = Set(x)} // factory for Set containers
def wrapItemInContainer[ M[A]: ContainerFactory, A](item: A, helper: M[A]) : M[A] = {
val c = implicitly[ContainerFactory[M]]
c.put(item)
}
var j: List[Int] = wrapItemInContainer(9, List(0))
Ma voglio davvero qualcosa con il secondo argomento rumorosa:
def wrapItemInContainer[ M[A]: ContainerFactory, A](item: A) : M[A] = {
val c = implicitly[ContainerFactory[M[A]]]
c.put(item)
}
var j: List[Int] = wrapItemInContainer(9) // this does not work.
ottengo questo errore:
<console>:17: error: ambiguous implicit values:
both value factory of type => ContainerFactory[List]
and value factory2 of type => ContainerFactory[Set]
match expected type ContainerFactory[M]
var j: List[Int] = wrapItemInContainer(9)
Tutte le idee o i consigli sono molto apprezzati!
-Chris
Per farti sapere: questo è ciò che a volte viene chiamato "Puntato". Di solito fa parte della classe di tipo Applicativo, ad es. In [scalaz] (https://github.com/scalaz/scalaz/blob/466d4da2951666f736d554104a2b3b956e4e6885/core/src/main/scala/scalaz/Applicative.scala). – phg