Ben aşağıdaki kodu traverse_
fonksiyonun tipi çıkarsama geliştirmeye çalışıyorum: Yukarıdaki KoşuScala'da kısmen uygulanan türlerin tür çıkarımını geliştirmek mümkün mü?
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)
verir:
/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
Belirtmemeyi var, derlemek almak için Ben traverse_
yeniden bir yolu var mı
val y = traverse_[({type l[x]=Either[String, x]})#l, Int](1 to 10) {
case 5 => Left("x")
case _ => Right(())
}
veya: traverse_
argümanlar yazın tür çıkarımı yapmak için, kodun herhangi bir parçası? Türler daha karmaşıklaşmaya başladığında, bu hızlı sinirlenir.
Miles Sabin, Scalaz'da "traverseU" uygulamasında kullanılan bir yolu keşfetti. Tam olarak ne yapmaya çalıştığın gibi geliyor. –