简体   繁体   English

基本的Scalaz State问题

[英]Basic Scalaz State question

How do I use State to mimic the behaviour of List.zipWithIndex ? 如何使用State来模仿List.zipWithIndex的行为? What I have come up with so far (which doesn't work) is: 到目前为止我提出的(不起作用)是:

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)] )
}

This is based very loosely on the state example . 这基于状态示例非常松散。 As I said, it does not work: 正如我所说,它不起作用:

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))

I can get it to work by changing a line of the case statement: 我可以通过更改case语句的一行来使它工作:

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

But this just feels wrong. 但这只是错了。 Can anyone help? 有人可以帮忙吗?

EDIT - more playing around has got me to this 编辑 - 更多的游戏让我有了这个

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)) { _ ::: _ }
  }
}

Can it be improved? 可以改进吗? Can it be generalized to containers other than List (and, if so, what typeclasses are needed?) 可以将它推广到List以外的容器(如果需要,还需要哪些类型类?)

EDIT 2 - I have now generalized it, albeit a bit clunkily 编辑2 - 我现在已经概括了它,虽然有点笨拙

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)}  } )
}

Or the very similar: 或者非常相似:

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)}  } )
}
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

Or even... 甚至...

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

See The Essence of the Iterator Pattern for more on traversing with State. 有关遍历状态的更多信息,请参阅迭代器模式的本质

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM