स्काला में पर काम कर के साथ उत्पाद के प्रकार को लागू स्काला में, मैं एक उत्पाद के प्रकार &
कि एक यौगिक मूल्य का प्रतिनिधित्व करता, उदा .:सामान्य अद्यतन समारोह अपने हिस्से
val and: String & Int & User & ... = ???
यानी बनाने की जरूरत and
में String
भाग और Int
भाग और User
भागों के अंदर होना चाहिए। यह स्काला with
कीवर्ड के समान है:
val and: String with Int with User with ... = ???
होने ऐसे उत्पाद प्रकार मैं करने के लिए कोई तरीका होना चाहिए, एक समारोह A => A
, कुछ उत्पाद मूल्य के लिए इसे लागू करते हैं और उस उत्पाद A
हिस्सा बदल के साथ वापस मिलता है। इसका तात्पर्य है कि उत्पाद में प्रत्येक प्रकार अद्वितीय होना चाहिए - यह स्वीकार्य है।
एक महत्वपूर्ण सीमा यह है कि, उत्पाद को A => A
पर लागू करने पर, मुझे केवल इतना पता है कि उत्पाद में कहीं भी A
है लेकिन इसमें अन्य प्रकारों के बारे में कोई जानकारी नहीं है। लेकिन फ़ंक्शन के कॉलर के रूप में, मैं इसे पूर्ण प्रकार की जानकारी वाले उत्पाद को पास करता हूं और फ़ंक्शन हस्ताक्षर के हिस्से के रूप में इस पूर्ण प्रकार को वापस पाने की अपेक्षा करता हूं।
छद्म कोड में:
def update[A, Rest](product: A & Rest, f: A => A): A & Rest
निराकार या अन्य गूढ़ सामान का उपयोग करना मेरे लिए ठीक है। मैंने HList
एस का उपयोग करने की कोशिश की लेकिन उन्हें आदेश दिया गया है, जबकि विषम सेट की तरह कुछ A & Rest
भाग को दोबारा भेजने के लिए यहां अधिक उपयुक्त होगा।
अद्यतन:
object product {
/** Product of `left` and `right` values. */
case class &[L, R](left: L, right: R)
implicit class AndPimp[L](val left: L) extends AnyVal {
/** Make a product of `this` (as left) and `right`. */
def &[R](right: R): L & R = new &(left, right)
}
/* Updater. */
/** Product updater able to update value of type `A`. */
trait ProductUpdater[P, A] {
/** Update product value of type `A`.
* @return updated product */
def update(product: P, f: A ⇒ A): P
}
trait LowPriorityProductUpdater {
/** Non-product value updater. */
implicit def valueUpdater[A]: ProductUpdater[A, A] = new ProductUpdater[A, A] {
override def update(product: A, f: A ⇒ A): A = f(product)
}
}
object ProductUpdater extends LowPriorityProductUpdater {
/** Left-biased product value updater. */
implicit def leftProductUpdater[L, R, A](implicit leftUpdater: ProductUpdater[L, A]): ProductUpdater[L & R, A] =
new ProductUpdater[L & R, A] {
override def update(product: L & R, f: A ⇒ A): L & R =
leftUpdater.update(product.left, f) & product.right
}
/** Right-biased product value updater. */
implicit def rightProductUpdater[L, R, A](implicit rightUpdater: ProductUpdater[R, A]): ProductUpdater[L & R, A] =
new ProductUpdater[L & R, A] {
override def update(product: L & R, f: A ⇒ A): L & R =
product.left & rightUpdater.update(product.right, f)
}
}
/** Update product value of type `A` with function `f`.
* Won't compile if product contains multiple `A` values.
* @return updated product */
def update[P, A](product: P)(f: A ⇒ A)(implicit updater: ProductUpdater[P, A]): P =
updater.update(product, f)
/* Reader. */
/** Product reader able to read value of type `A`. */
trait ProductReader[P, A] {
/** Read product value of type `A`. */
def read(product: P): A
}
trait LowPriorityProductReader {
/** Non-product value reader. */
implicit def valueReader[A]: ProductReader[A, A] = new ProductReader[A, A] {
override def read(product: A): A = product
}
}
object ProductReader extends LowPriorityProductReader {
/** Left-biased product value reader. */
implicit def leftProductReader[L, R, A](implicit leftReader: ProductReader[L, A]): ProductReader[L & R, A] =
new ProductReader[L & R, A] {
override def read(product: L & R): A =
leftReader.read(product.left)
}
/** Right-biased product value reader. */
implicit def rightProductReader[L, R, A](implicit rightReader: ProductReader[R, A]): ProductReader[L & R, A] =
new ProductReader[L & R, A] {
override def read(product: L & R): A =
rightReader.read(product.right)
}
}
/** Read product value of type `A`.
* Won't compile if product contains multiple `A` values.
* @return value of type `A` */
def read[P, A](product: P)(implicit productReader: ProductReader[P, A]): A =
productReader.read(product)
// let's test it
val p = 1 & 2.0 & "three"
read[Int & Double & String, Int](p) // 1
read[Int & Double & String, Double](p) // 2.0
read[Int & Double & String, String](p) // three
update[Int & Double & String, Int](p)(_ * 2) // 2 & 2.0 & three
update[Int & Double & String, Double](p)(_ * 2) // 1 & 4.0 & three
update[Int & Double & String, String](p)(_ * 2) // 1 & 2.0 & threethree
}
बारे में 'HList' ordere किया जा रहा है डी: यह कभी तय नहीं किया जा सकता है। जबकि आप विधियों/प्रकारों को परिभाषित कर सकते हैं जो दो उत्पादों की तुलना करेंगे और आपको बताएंगे कि ऑर्डरिंग के बावजूद उनके पास एक ही प्रकार है, जब प्रति प्रकार की प्रणाली की बात आती है तो आप भाग्य से बाहर हैं। आप हर जादू को आजमा सकते हैं, आप कभी भी कंपाइलर को यह सोचने में सक्षम नहीं होंगे कि '& [Int, String] '' और [स्ट्रिंग, Int]' जैसा ही है (एक कंपाइलर प्लगइन को लागू करने से कम जो पूरी तरह से खत्म हो जाएगा उन प्रकारों के लिए प्रकार की जांच, यदि यह भी संभव है)। –
@ रेजीज-गिल्स, इसे मिला, धन्यवाद। – Tvaroh