2010-12-30 17 views
12

Jak używać State do naśladowania zachowania List.zipWithIndex? Co mam wymyślić tak daleko (który nie działa) jest:Podstawowe pytanie dotyczące stanu skalowania

def numberSA[A](list : List[A]) : State[Int, List[(A, Int)]] = list match { 
    case x :: xs => (init[Int] <* modify((_:Int) + 1)) map { s : Int => (x -> s) :: (numberSA(xs) ! s) } 
    case Nil  => state((i : Int) => i -> nil[(A, Int)]) 
} 

ten oparty jest bardzo luźno na state example. Jak powiedziałem, to nie działa:

scala> res4 
res5: List[java.lang.String] = List(one, two, three) 

scala> numberSA(res4) ! 1 
res6: List[(String, Int)] = List((one,1), (two,1), (three,1)) 

mogę zmusić go do pracy, zmieniając linię rachunku koperty:

case x :: xs => (init[Int]) map { s : Int => (x -> s) :: (numberSA(xs) ! (s + 1)) } 

Ale to po prostu czuje się źle. Czy ktoś może pomóc?

EDIT - więcej zabawy ma mnie do tego

def numberSA[A](list : List[A]) : State[Int, List[(A, Int)]] = { 
    def single(a : A) : State[Int, List[(A, Int)]] = (init[Int] <* modify((_ : Int) + 1)) map { s : Int => List(a -> s) } 
    list match { 
    case Nil  => state((_ : Int) -> nil[(A, Int)]) 
    case x :: xs => (single(x) <**> numberSA(xs)) { _ ::: _ } 
    } 
} 

można go poprawić? Może być uogólnione do pojemników innych niż List (a jeśli tak, to jakie typeclasses są potrzebne?)

EDIT 2 - Mam teraz uogólnić go, choć trochę clunkily

def index[M[_], A](ma : M[A]) 
     (implicit pure : Pure[M], empty : Empty[M], semigroup : Semigroup[M[(A, Int)]], foldable : Foldable[M]) 
     : State[Int, M[(A, Int)]] = { 
    def single(a : A) : State[Int, M[(A, Int)]] = (init[Int] <* modify((_ : Int) + 1)) map { s : Int => pure.pure(a -> s) } 
    foldable.foldLeft(ma, state((_ : Int) -> empty.empty[(A, Int)]), { (s : State[Int, M[(A, Int)]],a : A) => (s <**> single(a)) { (x,y) => semigroup.append(x,y)} }) 
} 

Albo bardzo podobny:

def index[M[_] : Pure : Empty : Plus : Foldable, A](ma : M[A]) 
    : State[Int, M[(A, Int)]] = { 
    import Predef.{implicitly => ??} 
    def single(a : A) : State[Int, M[(A, Int)]] = (init[Int] <* modify((_ : Int) + 1)) map { s : Int => ??[Pure[M]].pure(a -> s) } 
    ??[Foldable[M]].foldLeft(ma, state((_ : Int) -> ??[Empty[M]].empty[(A, Int)]), { (s : State[Int, M[(A, Int)]],a : A) => (s <**> single(a)) { (x,y) => ??[Plus[M]].plus(x,y)} }) 
} 

Odpowiedz

9
def index[M[_]:Traverse, A](m: M[A]) = 
    m.traverse[({type λ[x] = State[Int,x]})#λ, (A, Int)](a => 
    state(i => (i + 1, (a, i)))) ! 0 

Albo nawet ...

def index[M[_]:Traverse, A](m: M[A]) = 
    m.traverse[({type λ[x] = State[Int,x]})#λ, (A, Int)](a => 
    (Lens.self[Int] += 1) map ((a, _)) ! -1 

Zobacz The Essence of the Iterator Pattern więcej na przejeżdżające z państwa.

+0

I był mnie, czując się cały sprytny –

Powiązane problemy