So I was writing a small toybox of utility functions for CSV files and throughout testing the functions I'd been binding the file by hand with
table' <- parseCSVFromFile filepath
but (from Text.CSV) 
parseCSVFromFile :: FilePath -> IO (Either parsec-3.1.9:Text.Parsec.Error.ParseError CSV)
and so I had to write a quick line to strip off this either error csv crap
stripBare csv = head $ rights $ flip (:) [] csv
and redefine it as table = stripBare table'. After this, list functions work on the csv files contents and life goes on
(Digression: Surprisingly there isn't a direct Either a b -> b function in Data.Either. So I used Data.Either.rights :: [Either a b] -> [b])
I wanted to do the work of undressing the csv type and binding it to a handle in one shot. Something like
table = stripBare $ table' <- parseCSVFromFile filepath
but this gives a parse error on (<-) saying I may be missing a do... then
table = stripBare $ do table' <- parseCSVFromFile filepath
yells at me saying that the last statement in a do block must be an expression.
What am I doing wrong?
As a separate curiosity, I saw here that
do notation in Haskell desugars in a pretty simple way.
do
  x <- foo
  e1 
  e2
  ...
turns into
 foo >>= \x ->
 do
   e1
   e2
I find this attractive and tried the following line which gave me a type error
*Toy> :type (parseCSVFromFile "~/.csv") >>= \x -> x
<interactive>:1:52: error:
    * Couldn't match type `Either
                             parsec-3.1.9:Text.Parsec.Error.ParseError'
                     with `IO'
      Expected type: IO CSV
        Actual type: Either parsec-3.1.9:Text.Parsec.Error.ParseError CSV
    * In the expression: x
      In the second argument of `(>>=)', namely `\ x -> x'
      In the expression:
        (parseCSVFromFile "~/.csv") >>= \ x -> x
 
     
    