Q:

Why two definitions of 'reverse' in Haskell's Data.List

Looking at the source of Data.List shows reverse defined as
#ifdef USE_REPORT_PRELUDE
reverse                 =  foldl (flip (:)) []
#else
reverse l =  rev l []
  where
    rev []     a = a
    rev (x:xs) a = rev xs (x:a)
#endif

I would like to know why the second definition is provided? Is it superior in some sense?
EDIT: 
As @n.m. comments below, the second version is "like a straightforward rewrite of the first version, with foldl expanded and flip (:) inlined into it." Indeed, Data.List itself defines foldl as
foldl        :: (b -> a -> b) -> b -> [a] -> b
foldl f z0 xs0 = lgo z0 xs0
             where
                lgo z []     =  z
                lgo z (x:xs) = lgo (f z x) xs

It is impossible to know the motivation of the authors of Data.List (unless one of them happens to visit this page), but as a beginner is it OK if I write code like the first version of reverse and leave the compiler to do the inlining for me?

A:

I believe that the first version,
reverse                 =  foldl (flip (:)) []

is the version of reverse defined in the Haskell Report, and the second version
reverse l =  rev l []
  where
    rev []     a = a
    rev (x:xs) a = rev xs (x:a)

is an equivalent function which is more efficient.  You can see that the second version uses an accumulation parameter so the whole thing is a tail call, which is very efficient on most Haskell implementations.
The second version is the one provided by default, perhaps the first one is provided so that the compiler writers can test how well programs perform with the more concise function definitions in the report.
Note: it appears others came to the same conclusion, in a post to haskell-cafe.

A:

We can compile copies of these two versions and see what ghc outputs.
module Rev where

myReverse1                 =  foldl (flip (:)) []
myReverse2 l =  rev l []
  where
    rev []     a = a
    rev (x:xs) a = rev xs (x:a)

Building with -ddump-simpl to see the generated core, and -dsuppress-all to eliminate some irrelevant noise:
rwbarton@morphism:/tmp$ ghc -O -ddump-simpl -dsuppress-all -fforce-recomp Rev
[1 of 1] Compiling Rev              ( Rev.hs, Rev.o )

==================== Tidy Core ====================
Result size of Tidy Core = {terms: 40, types: 58, coercions: 0}

Rec {
myReverse3
myReverse3 =
  \ @ a_aNh z_aNB ds_aNC ->
    case ds_aNC of _ {
      [] -> z_aNB;
      : x_aNH xs_aNI -> myReverse3 (: x_aNH z_aNB) xs_aNI
    }
end Rec }

myReverse1
myReverse1 = \ @ a_aNh xs0_aNz -> myReverse3 ([]) xs0_aNz

Rec {
myReverse4
myReverse4 =
  \ @ a_aMV ds_dNu a1_auj ->
    case ds_dNu of _ {
      [] -> a1_auj;
      : x_auk xs_aul -> myReverse4 xs_aul (: x_auk a1_auj)
    }
end Rec }

myReverse2
myReverse2 = \ @ a_aMV l_auh -> myReverse4 l_auh ([])

Examination of myReverse3 versus myReverse4 shows that they are the same, except that they take their arguments in the opposite order. Indeed, you can see that lgo in foldl has its arguments reversed from rev in myReverse2. I'm pretty sure there is no noticeable performance difference as a result of this, and if there is it's unintentional.
So, yes, with optimizations GHC will compile the two definitions of reverse to essentially the same thing. My guesses for why the inlined definition exists are

The implementation of most of the standard library dates from a very long time ago and used to be shared between GHC, Hugs, and a couple of other Haskell compilers. Maybe GHC or one of the other systems was not so good at optimization back then.
It's still slightly useful today to have these manually optimized versions, when doing GHC development: it's commonplace to build the compiler and its libraries with optimizations disabled (since it's significantly faster), and then manual optimizations like this one means the resulting compiler, and the programs it produces, are more efficient actually, I checked and the common "quick" BuildFlavour still builds the libraries with -O, so there is not much truth to this after all.

