Using quickCheck for "99 Haskell problems" - problem 1 I'm working on learning Haskell, and I've implemented a solution to the first of the 99 Haskell problems. Here is my code:

import Data.Int
import Test.QuickCheck

myLast :: [a] -&gt; Either String a
myLast [] = Left "Empty lists have no last element."
myLast xs = Right ((reverse xs) !! 0)

testMyLast :: [Int] -&gt; Bool
testMyLast xs =
    case myLast xs of
        Left err -&gt; null xs
        Right x -&gt; x == last xs

main = quickCheck testMyLast


Now, I realize that my implementation of myLast is not the most efficient one. I'm not particularly interested in that type of feedback. Rather, I'm more curious about whether or not I'm following reasonable Haskell code style practices (the naming of things, indentation, etc.), as well as how I'm dealing with errors.

It's my understanding that using Either (or Maybe) when an error occurs is, in general, to be preferred over error "...", since dealing with exceptions is really only cleanly done in an IO context. Is my understanding correct? If it is, why do basic library functions (like List's last, for example) use error instead?
Most important point: Your answer does not do what is asked.

Question:


Prelude&gt; myLast [1,2,3,4]
4
Prelude&gt; myLast ['x','y','z']
'z'



Your implementation:

*Main&gt; myLast [1,2,3,4]
Right 4


You should quickCheck for the equivalence of the function you are asked to implement myLast xs == last xs (with appropriate type signatures),
or write a unit test suite comprising at least the cases given.

Other points:


import Data.Int is unused.
(xs !! 0) should be head xs
Nested parentheses should be used sparingly because trying to match them reduces readability. Composition using operators . and $ should be preferred:

-- instead of this
myLast xs = Right (head (reverse xs))
-- this reads better
myLast' xs = Right $ head $ reverse xs
-- this makes the composition of 3 steps more explicit
myLast'' = Right . head . reverse