2

I want a function that takes in a list and indexes out all the contents: indexed :: [a] -> [(Int, a)]. Or the returned value can be whatever Monad as long as it contains indexed values of the original list.

I thought that I would need StateT to temporary remember and inclement index numbers while processing each element, but I'm not familiar with Monad transformer thingy and I need some help write the function.

I believe it will look similar to this (this is sure not working):

indexed ns = do
  n <- ns
  i <- get
  put (i + 1)
  return (i, n)

How would you write it?

Ryoichiro Oka
  • 1,949
  • 2
  • 13
  • 20

1 Answers1

6

No need to go to all that trouble.

indexed = zip [0..]

If you want to use monad transformers, I think there’s this:

indexed :: [a] -> [(Int, a)]
indexed ns = evalState (runListT lt) 0 where
    lt = do
        n <- ListT $ return ns
        i <- get <* modify (+1)
        return (i, n)
Ry-
  • 218,210
  • 55
  • 464
  • 476
  • Haha that's clever! Thanks for your answer. But I'm still wondering how it could be implemented within Monad transformer. – Ryoichiro Oka Jul 08 '15 at 00:36
  • 1
    @RyoichiroOka There's different ways to do that in [this question](http://stackoverflow.com/questions/29125149/how-would-i-use-lens-in-haskell-to-duplicate-pythons-enumerate). – cchalmers Jul 08 '15 at 00:49
  • 1
    @RyoichiroOka: Edited. – Ry- Jul 08 '15 at 01:04
  • 5
    @RyoichiroOka, just clearing up in case you have a mistake in your mind: `zip [0..]` is not some clever hack that works in this case where in general you need a state transformer; rather, state is almost never necessary and most problems can be solved by combining standard functions. State really should be one of your last resorts. – luqui Jul 08 '15 at 01:39