<p dir="ltr">I'm generally +1 on this concept, but I'd like to see some evidence that there is no measurable performance impact on nofib and perhaps also other benchmarks, particularly for very short ephemeral lists. Note that saving the index requires actually putting it somewhere.</p>
<div class="gmail_quote">On Oct 16, 2014 2:21 AM, "Simon Hengel" <<a href="mailto:sol@typeful.net">sol@typeful.net</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi,<br>
currently we have the following implementation for (!!):<br>
<br>
    #ifdef USE_REPORT_PRELUDE<br>
    xs     !! n | n < 0 =  error "Prelude.!!: negative index"<br>
    []     !! _         =  error "Prelude.!!: index too large"<br>
    (x:_)  !! 0         =  x<br>
    (_:xs) !! n         =  xs !! (n-1)<br>
    #else<br>
    -- HBC version (stolen), then unboxified<br>
    xs !! (I# n0) | isTrue# (n0 <# 0#) =  error "Prelude.(!!): negative index\n"<br>
                  | otherwise          =  sub xs n0<br>
                             where<br>
                                sub :: [a] -> Int# -> a<br>
                                sub []     _ = error "Prelude.(!!): index too large\n"<br>
                                sub (y:ys) n = if isTrue# (n ==# 0#)<br>
                                               then y<br>
                                               else sub ys (n -# 1#)<br>
    #endif<br>
<br>
I propose to change the error messages for the non-report version to<br>
include index and list length, something that is functionally equivalent<br>
to:<br>
<br>
    xs !! (I# n0) | isTrue# (n0 <# 0#) =  indexError xs n0<br>
                  | otherwise          =  sub xs n0<br>
                             where<br>
<br>
                                sub :: [a] -> Int# -> a<br>
                                sub []     _ = indexError xs n0<br>
                                sub (y:ys) n = if isTrue# (n ==# 0#)<br>
                                               then y<br>
                                               else sub ys (n -# 1#)<br>
    indexError :: [a] -> Int# -> b<br>
    indexError xs (I# -> n)<br>
      | n < 0 = error ("Prelude.(!!): negative index " ++ show n)<br>
      | otherwise = error ("Prelude.(!!): index " ++ show n ++ " too large for list of length " ++ show (length xs))<br>
<br>
Some usage examples:<br>
<br>
    *Main> [1, 2, 3] !! (-1)<br>
    *** Exception: Prelude.(!!): negative index -1<br>
    *Main> [1, 2, 3] !! 3<br>
    *** Exception: Prelude.(!!): index 3 too large for list of length 3<br>
<br>
This will require some refactoring, i.e. we need to move itos from<br>
GHC.Show to e.g. GHC.Base.<br>
<br>
Discussion period: 2 weeks<br>
<br>
Cheers,<br>
Simon<br>
_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://www.haskell.org/mailman/listinfo/libraries" target="_blank">http://www.haskell.org/mailman/listinfo/libraries</a><br>
</blockquote></div>