    module System.Information.CPU ( cpuLoad ) where

    import Control.Concurrent ( threadDelay )
    import System.IO ( IOMode(ReadMode), openFile, hGetLine, hClose )

    procData :: IO [Double]
    procData = do
      h <- openFile "/proc/stat" ReadMode
      firstLine <- hGetLine h
      (length firstLine) `seq` return ()
      hClose h
      return (procParser firstLine)

    procParser :: String -> [Double]
    procParser = map read . tail . words

    truncVal :: Double -> Double
    truncVal v
      | isNaN v || v < 0.0 = 0.0
      | otherwise = v

    -- | Return a pair with (user time, system time, total time) (read
    -- from /proc/stat).  The function waits for 50 ms between samples.
    cpuLoad :: IO (Double, Double, Double)
    cpuLoad = do
      a <- procData
      threadDelay 50000
      b <- procData
      let dif = zipWith (-) b a
          tot = foldr (+) 0 dif
          pct = map (/ tot) dif
          user = foldr (+) 0 $ take 2 pct
          system = pct !! 2
          t = user + system
      return (truncVal user, truncVal system, truncVal t)