>>> ['a', 'b', 'c'] !? 0 Just 'a'
>>> ['a', 'b', 'c'] !? 2 Just 'c'
>>> ['a', 'b', 'c'] !? 3 Nothing
>>> ['a', 'b', 'c'] !? (-1) Nothing
[2,3,4] !? 1 == Just 3 [2,3,4] !? (-1) == Nothing [] !? 0 == Nothing
>>> ['a', 'b', 'c'] !? 0 Just 'a' >>> ['a', 'b', 'c'] !? 2 Just 'c' >>> ['a', 'b', 'c'] !? 3 Nothing >>> ['a', 'b', 'c'] !? (-1) NothingThis is the total variant of the partial !! operator. WARNING: This function takes linear time in the index.
>>> [] !!? 0 Nothing
>>> ["a", "b", "c"] !!? 3 Nothing
>>> [1, 2, 3] !!? (-1) Nothing
>>> ["a", "b", "c"] !!? 2 Just "c"
copy mv v = ... write mv i (v ! i) ...For lazy vectors, v ! i would not be evaluated which means that mv would unnecessarily retain a reference to v in each element written. With indexM, copying can be implemented like this instead:
copy mv v = ... do x <- indexM v i write mv i xHere, no references to v are retained because indexing (but not the elements) is evaluated eagerly.
unsafeIndex :: v a -> Int -> ainstead. Now, if we wanted to copy a vector, we'd do something like
copy mv v ... = ... unsafeWrite mv i (unsafeIndex v i) ...For lazy vectors, the indexing would not be evaluated which means that we would retain a reference to the original vector in each element we write. This is not what we want! With basicUnsafeIndexM, we can do
copy mv v ... = ... case basicUnsafeIndexM v i of Box x -> unsafeWrite mv i x ...which does not have this problem because indexing (but not the returned element!) is evaluated immediately.
>>> maybeAt 0 [] Nothing
>>> maybeAt 3 ["a", "b", "c"] Nothing
>>> maybeAt (-1) [1, 2, 3] Nothing
>>> maybeAt 2 ["a", "b", "c"] Just "c"
>>> fromReverseListN 3 [1,2,3] :: Data.Vector.Vector Int [3,2,1]