2

I'm stuck trying to reduce a list inside a state monad using a function returning State:

def op(t1: T, t2: T): State[S, T] 
val list: State[S, List[T]]

I'd like to reduce the list to get a State[S, T]

Magnus Eklund
  • 649
  • 6
  • 9

1 Answers1

4

It's not possible to do this operation safely as written (what happens if the list is empty?), but if you have an identity element for op, you can use foldLeftM from Foldable:

list.flatMap(_.foldLeftM[({ type L[x] = State[S, x] })#L, T](opId)(op))

Alternatively you could write something like this:

list.flatMap {
  case h :: t => t.foldLeftM[({ type L[x] = State[S, x] })#L, T](h)(op)
  case Nil => ???
}

Unfortunately in both cases the type parameters are necessary (type inference won't work here), so you'd probably want to define a type alias and avoid the type lambda if you were doing much of this kind of thing.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
  • I guess, one can also use an unsafe variant: `list.flatMap(l => l.tail.foldLeftM(l.head)(op))` – Kolmar Dec 19 '15 at 22:36
  • @Kolmar If you care enough about safety to put up with the state monad that's unlikely to be something you'd choose to do. – Travis Brown Dec 19 '15 at 22:43
  • @TravisBrown Works perfectly, thank you very much. I was pretty close to the solution actually but tried to solve the type inference issue using a type alias instead of a type lambda. Compilation failed due to missing Monad evidence for my type alias – Magnus Eklund Dec 19 '15 at 23:07