content: -- | Unsafe code posted <https://www.reddit.com/r/haskell/comments/3vlb8v/reading_data_problems/ on Reddit> and turned into safe code using NonEmpty.
  
  module NonEmptyListExample where
  
  -- <http://hackage.haskell.org/package/split split> utility library
  import qualified Data.List.Split as Split
  
  import qualified Data.List.NonEmpty as NonEmpty
  import Data.List.NonEmpty (NonEmpty)
  
  -- Our utility module.
  import qualified Sort3
  
  main :: IO ()
  main = do
      contents <- readFile "input.txt"
      case NonEmpty.nonEmpty contents of
        Nothing -> return ()
        Just contents1 -> putStrLn $ show (totalArea(parseFile contents1))
  
  totalArea :: NonEmpty (Int, Int, Int) -> Int
  totalArea xs = foldl (\acc x -> (acc + partialArea x)) 0 xs
  
  partialArea :: (Int, Int, Int) -> Int
  partialArea (l, w, h) = 2 * (l*w + w*h + h*l) + slack
    where
      areas :: NonEmpty Int
      areas = NonEmpty.fromList [l, w, h]
  
      -- 'maximum' is safe on 'NonEmpty'
      -- But 'smallSides' can be empty because of 'NonEmpty.filter',
      -- and 'NonEmpty.fromList' is unsafe!
      smallSides :: [Int]
      smallSides = NonEmpty.filter (< maximum areas) areas
  
      -- unsafe!
      smallSides1 :: NonEmpty Int
      smallSides1 = NonEmpty.fromList smallSides
  
      -- 'foldl1' is safe on 'NonEmpty'
      slack = foldl1 (*) smallSides1
  
  parseFile :: NonEmpty Char -> NonEmpty (Int, Int, Int)
  parseFile xs = NonEmpty.map (splitDimensions) (breakLines xs)
  
  -- | We ended up not needing the fact that the input is nonempty, and
  -- converted it to a regular list.
  breakLines :: NonEmpty Char -> NonEmpty String
  breakLines string1 = ourSplitOn "\n" (NonEmpty.toList string1)
  
  -- | 'read' is unsafe. '(!!)' is unsafe.
  splitDimensions :: String -> (Int, Int, Int)
  splitDimensions xs = (item 0, item 1, item 2)
                     where item n = read ((Split.splitOn "x" xs)!!n)
  
  -- | Using unsafe 'NonEmpty.fromList' is safe because we know
  -- the result 'from Split.splitOn' is nonempty. Note that the elements
  -- themselves can be empty.
  ourSplitOn :: Eq a => [a] -> [a] -> NonEmpty [a]
  ourSplitOn subList list = NonEmpty.fromList (Split.splitOn subList list)
  
  -- | Don't use lists at all!
  bestPartialArea :: (Int, Int, Int) -> Int
  bestPartialArea (l, w, h) = 2 * (l*w + w*h + h*l) + slack
    where
      (side0, side1, _) = Sort3.sort3 (l, w, h)
      slack = side0 * side1
  