content: -- A benchmark comparing hexp with integer.
  --
  -- To get the lowest results:
  --
  --  * define integer as an unsafe foreign call
  --
  --  * replace 'System.IO.Unsafe.unsafePerformIO' with
  --    'Control.Monad.Primitive.unsafeInlineIO' in the definition
  --    of 'hexp' and 'Foreign.R.typeOf'.
  --
  --  * Add an INLINE pragma for peekHExp
  --
  -- >    {-# INLINE peekHExp #-}
  --
  --  * redefine hexp as
  --
  -- >    hexp :: SEXP a -> HExp a
  -- >    hexp = unsafeInlineIO . peekHExp
  -- >    {-# INLINE hexp #-}
  --
  {-# LANGUAGE GADTs #-}
  {-# LANGUAGE DataKinds #-}
  
  import Foreign.R (integer, SEXP, SomeSEXP(..))
  import qualified Foreign.R as R (SSEXPTYPE, SEXPTYPE(Int), typeOf, cast)
  import H.Prelude (withEmbeddedR, defaultConfig)
  import Language.R.Literal (mkSEXPIO)
  import Language.R.HExp (hexp, HExp(..))
  import Data.Singletons (sing)
  
  import Control.Monad.Primitive
  import Criterion.Main
  import Data.Int
  import Data.Vector.SEXP (unsafeIndexM)
  import Foreign.Ptr (Ptr)
  import Foreign.Storable (peek)
  import System.IO.Unsafe (unsafePerformIO)
  
  
  main :: IO ()
  main = withEmbeddedR H.Prelude.defaultConfig $ do
      x <- mkSEXPIO (1 :: Int32)
      defaultMain
        [ bgroup "vector access"
            [ bench "typeof>integer"   $ whnfIO $ benchInteger x
            , bench "hexp>unsafeIndex" $ whnf benchHExp x
            , bench "unsafe-integer"   $ whnfIO $ benchUncheckedInteger x
            , bench "hexp-cast"        $ whnf benchCast (SomeSEXP x)
  
  --          , bench "unsafePerformIO" $ whnf unsafePerformIO $ return x
  --          , bench "unsafeInlineIO" $ whnf unsafeInlineIO $ return x
  --          , bench "(+)" $ whnf (\i -> i + 1) (1 :: Int)
            , bench "unsafePerformIO" $ whnf unsafePerformIO $ return x
            , bench "unsafeInlineIO" $ whnf unsafeInlineIO $ return x
            , bench "(+)" $ whnf (\i -> i + 1) (1 :: Int)
            ]
        ]
  
  benchInteger :: SEXP s 'R.Int -> IO Int32
  benchInteger x = do
      case R.typeOf x of
        R.Int -> integer x >>= (peek :: Ptr Int32 -> IO Int32)
        _ -> error "unexpected SEXP"
  
  benchHExp :: SEXP s a -> Int32
  benchHExp x =
      case hexp x of
        Int s -> unsafeInlineIO $ s `unsafeIndexM` 0
        _ -> error "unexpected SEXP"
  
  benchUncheckedInteger :: SEXP s 'R.Int -> IO Int32
  benchUncheckedInteger x = integer x >>= (peek :: Ptr Int32 -> IO Int32)
  
  benchCast :: SomeSEXP s -> Int32
  benchCast x =
   let y = R.cast (sing :: R.SSEXPTYPE 'R.Int) x
   in case hexp y of
        Int s -> unsafeInlineIO $ s `unsafeIndexM` 0
  