आप सभी Traversables के लिए ऐसा नहीं कर सकते, वे डॉन के रूप में यह गारंटी नहीं है कि नक्शा ट्रैवर्सबल से कुछ और विशिष्ट लौटाता है।
नीचे अपडेट 2 देखें।
import collection.generic.CanBuildFrom
import collection.TraversableLike
class TraversableW[CC[X] <: TraversableLike[X, CC[X]], A](value: CC[A]) {
def mapmap(f: A => A)(implicit cbf: CanBuildFrom[CC[A], A, CC[A]]): CC[A]
= value.map(f andThen f)
def mapToString(implicit cbf: CanBuildFrom[CC[A], String, CC[String]]): CC[String]
= value.map(_.toString)
}
object TraversableW {
implicit def TraversableWTo[CC[X] <: TraversableLike[X, CC[X]], A](t: CC[A]): TraversableW[CC, A]
= new TraversableW[CC, A](t)
}
locally {
import TraversableW._
List(1).mapmap(1+)
List(1).mapToString
// The static type of Seq is preserved, *and* the dynamic type of List is also
// preserved.
assert((List(1): Seq[Int]).mapmap(1+) == List(3))
}
अद्यतन मैं प्रदर्शित करने के लिए क्यों TraversableW
दो प्रकार पैरामीटर के बजाय एलेक्सी के समाधान के रूप में एक पैरामीटर स्वीकार करता है एक और pimped विधि, mapToString
जोड़ दिया है,। पैरामीटर CC
एक उच्च प्रकार का प्रकार है, यह मूल संग्रह के कंटेनर प्रकार का प्रतिनिधित्व करता है। दूसरा पैरामीटर, A
, मूल संग्रह के तत्व प्रकार का प्रतिनिधित्व करता है। विधि mapToString
इस प्रकार मूल कंटेनर प्रकार को एक अलग तत्व प्रकार के साथ वापस करने में सक्षम है: CC[String
।
अद्यतन 2 @oxbow_lakes टिप्पणी के लिए धन्यवाद, मैंने इसे फिर से विचार किया है। CC[X] <: Traversable[X]
, TraversableLike
को सीधे पंप करना वास्तव में संभव है। टिप्पणियां इनलाइन:
import collection.generic.CanBuildFrom
import collection.TraversableLike
class TraversableW[CC[X] <: Traversable[X], A](value: CC[A]) {
/**
* A CanBuildFromInstance based purely the target element type `Elem`
* and the target container type `CC`. This can be converted to a
* `CanBuildFrom[Source, Elem, CC[Elem]` for any type `Source` by
* `collection.breakOut`.
*/
type CanBuildTo[Elem, CC[X]] = CanBuildFrom[Nothing, Elem, CC[Elem]]
/**
* `value` is _only_ known to be a `Traversable[A]`. This in turn
* turn extends `TraversableLike[A, Traversable[A]]`. The signature
* of `TraversableLike#map` requires an implicit `CanBuildFrom[Traversable[A], B, That]`,
* specifically in the call below `CanBuildFrom[Traversable[A], A CC[A]`.
*
* Essentially, the specific type of the source collection is not known in the signature
* of `map`.
*
* This cannot be directly found instead we look up a `CanBuildTo[A, CC[A]]` and
* convert it with `collection.breakOut`
*
* In the first example that referenced `TraversableLike[A, CC[A]]`, `map` required a
* `CanBuildFrom[CC[A], A, CC[A]]` which could be found.
*/
def mapmap(f: A => A)(implicit cbf: CanBuildTo[A, CC]): CC[A]
= value.map[A, CC[A]](f andThen f)(collection.breakOut)
def mapToString(implicit cbf: CanBuildTo[String, CC]): CC[String]
= value.map[String, CC[String]](_.toString)(collection.breakOut)
}
object TraversableW {
implicit def TraversableWTo[CC[X] <: Traversable[X], A](t: CC[A]): TraversableW[CC, A]
= new TraversableW[CC, A](t)
}
locally {
import TraversableW._
assert((List(1)).mapmap(1+) == List(3))
// The static type of `Seq` has been preserved, but the dynamic type of `List` was lost.
// This is a penalty for using `collection.breakOut`.
assert((List(1): Seq[Int]).mapmap(1+) == Seq(3))
}
क्या अंतर है?हमें collection.breakOut
का उपयोग करना पड़ा, क्योंकि हम केवल Traversable[A]
से विशिष्ट संग्रह उप प्रकार को पुनर्प्राप्त नहीं कर सकते थे।
def map[B, That](f: A => B)(implicit bf: CanBuildFrom[Repr, B, That]): That = {
val b = bf(repr)
b.sizeHint(this)
for (x <- this) b += f(x)
b.result
}
Builder
b
मूल संग्रह है, जो तंत्र एक map
के माध्यम से गतिशील प्रकार संरक्षित करने के लिए है के साथ आरंभ नहीं हो जाता। हालांकि, हमारे CanBuildFrom
ने से सभी तर्कों को अस्वीकार कर दिया, प्रकार तर्क Nothing
के प्रकार से।
def breakOut[From, T, To](implicit b : CanBuildFrom[Nothing, T, To]) =
new CanBuildFrom[From, T, To] {
def apply(from: From) = b.apply();
def apply() = b.apply()
}
हम b.apply(from)
, कोई और अधिक फोन नहीं कर सकते हैं की तुलना में आप def foo(a: Nothing) = 0
कह सकते हैं: तुम सब Nothing
साथ कर सकते हैं उस पर ध्यान नहीं है, जो है कि वास्तव में क्या breakOut
करता है।
पूरी तरह से काम करता है! –
मैंने स्कालाज़ में थोड़ा अलग दृष्टिकोण लिया, जो थोड़ा अधिक शक्तिशाली है: http://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/CanBuildAnySelf.scala#L24 http: //github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/Functor.scala#L28 – retronym
मेरे पास इसे संपादित करने का अधिकार नहीं है, संक्षेप में, लेकिन शायद कोड का स्वरूपित आपके उदाहरण में आयात को शामिल करने के लिए ब्लॉक को बढ़ाया जाना चाहिए? चीयर्स! – pr1001