Insbesondere versuche ich meine Functor
Typklasse mit Applicative
zu erweitern.Scala: eine Trait-Methode auf eine implizite Klasse im Objekt des Elternattributs verschieben
trait Functor[F[_]] {
def fmap[A, B](r: F[A], f: A => B): F[B]
}
object Functor {
implicit class FunctorOps[A, F[_]: Functor](xs: F[A]) {
def fmap[B](f: A => B): F[B] = implicitly[Functor[F]].fmap(xs, f)
}
implicit def SeqFunctor: Functor[Seq] = new Functor[Seq] {
def fmap[A, B](r: Seq[A], f: A => B) = r map f
}
}
trait Applicative[F[_]] extends Functor[F] {
// What I want to do, but this *does not* work.
def fmap[A, B](r: F[A], f: A => B): F[B] = Functor.FunctorOps[A, F](r).fmap(f)
def pure[A](x: A): F[A]
def fapply[A, B](r: F[A], f: F[A => B]): F[B]
}
object Applicative {
implicit class ApplicativeOps[A, F[_]](a: F[A])(implicit F: Applicative[F]) {
def fapply[B](f: F[A => B]): F[B] = F.fapply(a, f)
}
implicit def SeqApplicative: Applicative[Seq] = new Applicative[Seq] {
def pure[A](x: A) = Seq(x)
def fapply[A, B](xs: Seq[A], fs: Seq[A => B]): Seq[B] = xs.flatMap(x => fs.map(_(x)))
}
}
Der Kern ist es mir fmap
für all Applicative
s umsetzen müssen, aber es sollte wirklich das gleiche Verfahren, wie es in meiner FunctorOps
Klasse definiert. Wie mache ich das auf die sauberste Art und Weise?
ich tun wollen müssen, was ich basiert auf der Idee macht einen gegebenen TypC der Verlängerung Lass, ohne seine Quelle zu ändern. Also: 1) Ich kann nichts über meinen 'Funktor'-Code ändern, einschließlich des Entfernens der impliziten Klasse. Was ist, wenn ich eine zufällige Typklasse erhalte, die ich erweitern möchte? 2) 'fmap' (oder welche Funktion ich erben von der Typklasse, die ich gegeben bin) ist möglicherweise nicht so einfach zu definieren in Bezug auf die Funktionen meiner typeclass. – allidoiswin
2) ist strittig. Wenn Sie die Methoden der Oberklasse nicht in Bezug auf die Unterklassen definieren können, lassen Sie sie einfach abstrakt und lassen Sie den Implementierer dazu kommen (wie in Haskell, wo es nur * (portabel) ist.). 1) Wenn Sie einige existierende, nicht modifizierbare Superklassen-Instanzen haben, müssen Sie nur Ihre Subklasseninstanz definieren, um sie auf die Superklasse zu verschieben (Sie können diese in ihrer eigenen Hilfsklasse abstrahieren ('Helper [F [_]] (f : Functor [F]) {...} '), aber * setze diese Einschränkung nicht auf die Unterklasse selbst) und stelle sicher, dass die Unterklassen- und Oberklassen-Instanzen nicht zusammen importiert werden. – HTNW