मैं नीचे दिए गए कोड में traverse_
समारोह के प्रकार निष्कर्ष सुधार करने के लिए कोशिश कर रहा हूँ:स्कैला में आंशिक रूप से लागू प्रकारों के लिए प्रकार अनुमान को बेहतर बनाना संभव है?
import scala.language.higherKinds
trait Applicative[AF[_]] {
def ap[A, B](a: AF[A])(f: AF[A => B]): AF[B]
def pure[A](a: A): AF[A]
def fmap[A, B](a: AF[A])(f: A => B): AF[B]
}
def traverse_[AP[_]: Applicative, A](xs: Iterable[A])(f: A => AP[Unit]): AP[Unit] = {
val ap = implicitly[Applicative[AP]]
(xs :\ ap.pure(())) { (x, acc) =>
val apFunc = ap.fmap(f(x))(a => identity[Unit] _)
ap.ap(acc)(apFunc)
}
}
implicit def optionAp = new Applicative[Option] {
def ap[A, B](a: Option[A])(f: Option[A => B]): Option[B] = f flatMap (a map _)
def pure[A](a: A) = Some(a)
def fmap[A, B](a: Option[A])(f: A => B) = a map f
}
implicit def eitherAp[L] = new Applicative[({type l[x]=Either[L, x]})#l] {
def ap[A, B](a: Either[L, A])(f: Either[L, A => B]): Either[L, B] = f.right flatMap (a.right map _)
def pure[A](a: A) = Right(a)
def fmap[A, B](a: Either[L, A])(f: A => B) = a.right map f
}
// silly, but compiles
val x = traverse_(1 to 10) {
case 5 => None
case _ => Some(())
}
println(x)
// also silly, but does not compile
val y = traverse_(1 to 10) {
case 5 => Left("x")
case _ => Right(())
}
println(y)
ऊपर चल रहा है देता है:
/Users/lodea/tmp/traverse.scala:49: error: no type parameters for method traverse_: (f: Int => AP[Unit])(implicit evidence$1: this.Applicative[AP])AP[Unit] exist so that it can be applied to arguments (Int => Product with Serializable with scala.util.Either[String,Unit])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : Int => Product with Serializable with scala.util.Either[String,Unit]
required: Int => ?AP
val y = traverse_(1 to 10) {
^
/Users/lodea/tmp/traverse.scala:49: error: type mismatch;
found : Int => Product with Serializable with scala.util.Either[String,Unit]
required: Int => AP[Unit]
val y = traverse_(1 to 10) {
^
two errors found
यह संकलित करने के लिए प्राप्त करने के लिए, मैं स्पष्ट करना पड़ता traverse_
तर्क टाइप करें:
val y = traverse_[({type l[x]=Either[String, x]})#l, Int](1 to 10) {
case 5 => Left("x")
case _ => Right(())
}
वहाँ एक रास्ता मैं traverse_
गठित कर सकता है, या टाइप अनुमान बनाने के लिए कोड का कोई अन्य भाग? जब प्रकार अधिक जटिल हो जाते हैं, तो यह कष्टप्रद तेज़ हो जाता है।
माइल्स सबिन ने ऐसा करने का एक तरीका खोजा, जिसका उपयोग स्कालज़ में 'ट्रैवर्सयू 'के कार्यान्वयन में किया जाता है। यह वैसे ही लगता है जो आप करने की कोशिश कर रहे हैं। –