A traversable may be labelled. To take this idea one step further, one may apply a function to any element of a traversable by its index.
import Control.Monad.State
updateAt :: forall a. Int -> (a -> a) -> [a] -> [a]
updateAt i f = flip evalState [0..] . traverse g
where
g :: a -> State [Int] a
g x = do
js <- get
case js of
[ ] -> error ""
(j: js') -> do
put js'
if j == i
then return (f x)
else return x
In Haskell, there is an attempt to generalize or otherwise sort out operations like this. First it was keys, then it grew up into lens. It is now a huge package. I am trying to make sense of it.
To this end, I am trying to do simple things first. One simple thing is what I started with — to label a traversable. Can it be done? Further, can it be done on a "low level"?
element
seems to be doing the same as my example above, so I checked its definition. It led me to Indexable
, then to this:
class ( Choice p, Corepresentable p, Comonad (Corep p)
, Traversable (Corep p), Strong p, Representable p, Monad (Rep p)
, MonadFix (Rep p), Distributive (Rep p), Costrong p, ArrowLoop p
, ArrowApply p, ArrowChoice p, Closed p
) => Conjoined p
I admit this is a bit over my head. I like how "indexable" sounds — it must be useful. But it also seems to be the hardest piece of Haskell ever written. I understand that Conjoined
is an advanced kind of a profunctor, so basically... a function? I am not sure what it might be, and how this all connects to keyed containers.
Is it applicable to my problem? What is it for? How can I make sense of it?