State
ist eine Art Alias für eine generische Art IndexedStateT
, die speziell die Funktionen darstellen, die den Zustand Typ als Zustands Berechnungen ändern:
type StateT[F[_], S, A] = IndexedStateT[F, S, S, A]
type State[S, A] = StateT[Id, S, A]
Es ist zwar nicht möglich, Ihre modify[S, T]
mit State
zu schreiben, ist es möglich, mit IndexedState
(der anderen Art Alias für IndexedStateT
ist, die den Effekt Typen Id
fixiert):
import scalaz._, Scalaz._
def transform[S, T](f: S => T): IndexedState[S, T, Unit] =
IndexedState(s => (f(s),()))
Sie können dies auch in for
-comprehensions verwenden (das ist immer ein wenig seltsam schien mir hat, da die monadische Typänderungen zwischen den Operationen, aber es funktioniert):
val s = for {
a <- init[Int];
_ <- transform[Int, Double](_.toDouble)
_ <- transform[Double, String](_.toString)
r <- get
} yield r * a
Und dann:
scala> s(5)
res5: scalaz.Id.Id[(String, String)] = (5.0,5.05.05.05.05.0)
In Ihrem Fall könnten Sie so etwas schreiben:
import shapeless._, shapeless.labelled.{ FieldType, field }
case class S[L <: HList](total: Int, scratch: L)
def addField[K <: Symbol, A, L <: HList](k: Witness.Aux[K], a: A)(
f: Int => Int
): IndexedState[S[L], S[FieldType[K, A] :: L], Unit] =
IndexedState(s => (S(f(s.total), field[K](a) :: s.scratch),()))
Und dann:
def contrivedAdd[L <: HList](n: Int) = for {
a <- init[S[L]]
_ <- addField('latestAdded, n)(_ + n)
r <- get
} yield r.total
(Dies kann nicht der beste Weg, um die Stücke des Aktualisierungsvorganges von Factoring, aber es wird gezeigt, wie die Grundidee funktioniert.)
Es ist auch erwähnenswert, dass, wenn Sie nicht über das Darstellen der egal Zustandstransformation als Zustandsberechnung, können Sie einfach imap
verwenden, um auf alle alten State
:
init[S[HNil]].imap(s =>
S(1, field[Witness.`'latestAdded`.T](1) :: s.scratch)
)
Diese Sie diese Operationen kompositorisch auf die gleiche Art und Weise zu verwenden, ist es nicht möglich, aber es kann alles, was Sie brauchen in einigen Situationen sein .
Wie wäre es mit 'def modify [S, T] (f: S => T): Zustand [T, Einheit] = Zustand ((s: S) => (f (s),()))'? – knutwalker
@knutwalker schlagen Sie vor, "State" zu erweitern und "Modify" zu überladen? – Sim
Nein, schreibe einfach diese Funktion irgendwo in deinen Code.Es besteht keine Notwendigkeit, etwas zu erweitern oder zu überlasten. – knutwalker