diff --git a/box-tuples.cabal b/box-tuples.cabal
--- a/box-tuples.cabal
+++ b/box-tuples.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                box-tuples
-version:             0.1.1.0
+version:             0.2.0.0
 synopsis:            A hack to use GHC.Prim primitives in GHCi
 description:         As of now, the GHCi interactive runtime is incapable of working on unboxed
                      tuples. In particular, it is unable to fully apply any function returning an
@@ -21,7 +21,8 @@
 cabal-version:       >=1.10
 
 library
-  exposed-modules:     Data.Tuple.Unboxed
+  exposed-modules:     Data.Tuple.Unboxed,
+                       Data.Tuple.Unboxed.Rep
   build-depends:       base == 4.*, ghc-prim
   hs-source-dirs:      src
   default-language:    Haskell2010
diff --git a/src/Data/Tuple/Unboxed.hs b/src/Data/Tuple/Unboxed.hs
--- a/src/Data/Tuple/Unboxed.hs
+++ b/src/Data/Tuple/Unboxed.hs
@@ -1,8 +1,10 @@
-{-# LANGUAGE UnboxedTuples, MagicHash #-}
+{-# LANGUAGE UnboxedTuples, MagicHash, CPP #-}
+{-# OPTIONS_GHC -fobject-code #-}
+#include "MachDeps.h"
 -------------------------------------------------------------------------------
 -- |
 -- Module      : Data.Tuple.Unboxed
--- Copyright   : (C) 2016 mniip
+-- Copyright   : (C) 2016,2020 mniip
 -- License     : MIT
 -- Maintainer  : mniip <mniip@mniip.com>
 -- Stability   : experimental
@@ -40,9 +42,14 @@
 --  * Aa = 'ArrayArray#'
 --  * b = 'ByteArray#'
 --  * c = 'Char#'
+--  * C = 'Compact#'
 --  * d = 'Double#'
 --  * f = 'Float#'
 --  * i = 'Int#'
+--  * li = INT32 (@if WORD\_SIZE_IN_BITS >= 32 then 'Int#' else 'Int32#'@)
+--  * lli = INT64 (@if WORD\_SIZE_IN_BITS >= 64 then 'Int#' else 'Int64#'@)
+--  * hi = 'Int16#'
+--  * hhi = 'Int8#'
 --  * Ma = 'MutableArray#'
 --  * MAa = 'MutableArrayArray#'
 --  * Mb = 'MutableByteArray#'
@@ -58,138 +65,184 @@
 --  * Tv = 'TVar#'
 --  * v = 'MutVar#'
 --  * w = 'Word#'
+--  * lw = WORD32 (@if WORD\_SIZE_IN_BITS >= 32 then 'Word#' else 'Word32#'@)
+--  * llw = WORD64 (@if WORD\_SIZE_IN_BITS >= 64 then 'Word#' else 'Word64#'@)
+--  * hw = 'Word16#'
+--  * hhw = 'Word8#'
 --  * Wp = 'Weak#'
 --
--- This module contains functions for all combinations of types that come up in
--- "GHC.Prim" but in principle other cases could be added too.
+-- This module contains functions for all combinations of types that have ever
+-- come up in "GHC.Prim" but in principle other cases could be added too.
 -------------------------------------------------------------------------------
-module Data.Tuple.Unboxed
-    (
-        composea1_,
-        composei1_,
-        composeo1_,
-        composed2ii,
-        composef2ii,
-        composei2i_,
-        composei2ii,
-        composes2s_,
-        composes2sa,
-        composes2sAa,
-        composes2sb,
-        composes2sc,
-        composes2sd,
-        composes2sf,
-        composes2si,
-        composes2sSa,
-        composes2sSMa,
-        composes2sSn,
-        composes2sSp,
-        composes2sMa,
-        composes2sMAa,
-        composes2sMb,
-        composes2sMv,
-        composes2so,
-        composes2sp,
-        composes2st,
-        composes2sTv,
-        composes2sv,
-        composes2sw,
-        composes2sWp,
-        composew2wi,
-        composew2ww,
-        compose_3pab,
-        compose_3pba,
-        composes3si_,
-        composes3spw,
-        composed4iwwi,
-        composes4siii,
-        decomposes2s_
-    )
-    where
+module Data.Tuple.Unboxed where
 
 import GHC.Prim
 
-composea1_ :: (Addr# -> (# a #)) -> Addr# -> (a -> r) -> r
+#if WORD_SIZE_IN_BITS >= 32
+#define INT32 Int#
+#define WORD32 Word#
+#else
+#define INT32 Int32#
+#define WORD32 Word32#
+#endif
+#if WORD_SIZE_IN_BITS >= 64
+#define INT64 Int#
+#define WORD64 Word#
+#else
+#define INT64 Int64#
+#define WORD64 Word64#
+#endif
+
+compose_1_ :: (a -> (# b #)) -> a -> (b -> r) -> r
 composei1_ :: (Int# -> (# a #)) -> Int# -> (a -> r) -> r
 composeo1_ :: (BCO# -> (# a #)) -> BCO# -> (a -> r) -> r
-composed2ii :: (Double# -> (# Int#, Int# #)) -> Double# -> (Int# -> Int# -> r) -> r
+composep1_ :: (Addr# -> (# a #)) -> Addr# -> (a -> r) -> r
+composew1_ :: (Word# -> (# a #)) -> Word# -> (a -> r) -> r
+compose_2ab :: (a -> (# Array# e, ByteArray# #)) -> a -> (Array# e -> ByteArray# -> r) -> r
+composeb2ib :: (ByteArray# -> (# Int#, ByteArray# #)) -> ByteArray# -> (Int# -> ByteArray# -> r) -> r
+composed2ii :: (Double# -> (# INT64, Int# #)) -> Double# -> (Int# -> Int# -> r) -> r
+composed2llii :: (Double# -> (# INT64, Int# #)) -> Double# -> (INT64 -> Int# -> r) -> r
 composef2ii :: (Float# -> (# Int#, Int# #)) -> Float# -> (Int# -> Int# -> r) -> r
+composehhi2hhihhi :: (Int8# -> (# Int8#, Int8# #)) -> Int8# -> (Int8# -> Int8# -> r) -> r
+composehhw2hhwhhw :: (Word8# -> (# Word8#, Word8# #)) -> Word8# -> (Word8# -> Word8# -> r) -> r
+composehi2hihi :: (Int16# -> (# Int16#, Int16# #)) -> Int16# -> (Int16# -> Int16# -> r) -> r
+composehw2hwhw :: (Word16# -> (# Word16#, Word16# #)) -> Word16# -> (Word16# -> Word16# -> r) -> r
 composei2i_ :: (Int# -> (# Int#, a #)) -> Int# -> (Int# -> a -> r) -> r
+composei2ib :: (Int# -> (# Int#, ByteArray# #)) -> Int# -> (Int# -> ByteArray# -> r) -> r
 composei2ii :: (Int# -> (# Int#, Int# #)) -> Int# -> (Int# -> Int# -> r) -> r
+composeli2ib :: (INT32 -> (# Int#, ByteArray# #)) -> INT32 -> (Int# -> ByteArray# -> r) -> r
+composelli2ib :: (INT64 -> (# Int#, ByteArray# #)) -> INT64 -> (Int# -> ByteArray# -> r) -> r
+composellw2ib :: (WORD64 -> (# Int#, ByteArray# #)) -> WORD64 -> (Int# -> ByteArray# -> r) -> r
+composelw2ib :: (WORD32 -> (# Int#, ByteArray# #)) -> WORD32 -> (Int# -> ByteArray# -> r) -> r
+composep2ib :: (Addr# -> (# Int#, ByteArray# #)) -> Addr# -> (Int# -> ByteArray# -> r) -> r
 composes2s_ :: (State# s -> (# State# t, a #)) -> State# s -> (State# t -> a -> r) -> r
-composes2sa :: (State# s -> (# State# t, Array# a #)) -> State# s -> (State# t -> Array# a -> r) -> r
-composes2sAa :: (State# s -> (# State# t, ArrayArray# #)) -> State# s -> (State# t -> ArrayArray# -> r) -> r
+composes2sa :: (State# s -> (# State# t, Array# e #)) -> State# s -> (State# t -> Array# e -> r) -> r
 composes2sb :: (State# s -> (# State# t, ByteArray# #)) -> State# s -> (State# t -> ByteArray# -> r) -> r
 composes2sc :: (State# s -> (# State# t, Char# #)) -> State# s -> (State# t -> Char# -> r) -> r
+composes2sC :: (State# s -> (# State# t, Compact# #)) -> State# s -> (State# t -> Compact# -> r) -> r
 composes2sd :: (State# s -> (# State# t, Double# #)) -> State# s -> (State# t -> Double# -> r) -> r
 composes2sf :: (State# s -> (# State# t, Float# #)) -> State# s -> (State# t -> Float# -> r) -> r
 composes2si :: (State# s -> (# State# t, Int# #)) -> State# s -> (State# t -> Int# -> r) -> r
-composes2sSa :: (State# s -> (# State# t, SmallArray# a #)) -> State# s -> (State# t -> SmallArray# a -> r) -> r
-composes2sSMa :: (State# s -> (# State# t, SmallMutableArray# u a #)) -> State# s -> (State# t -> SmallMutableArray# u a -> r) -> r
-composes2sSn :: (State# s -> (# State# t, StableName# a #)) -> State# s -> (State# t -> StableName# a -> r) -> r
-composes2sSp :: (State# s -> (# State# t, StablePtr# a #)) -> State# s -> (State# t -> StablePtr# a -> r) -> r
-composes2sMa :: (State# s -> (# State# t, MutableArray# u a #)) -> State# s -> (State# t -> MutableArray# u a -> r) -> r
-composes2sMAa :: (State# s -> (# State# t, MutableArrayArray# u #)) -> State# s -> (State# t -> MutableArrayArray# u -> r) -> r
+composes2sli :: (State# s -> (# State# t, INT32 #)) -> State# s -> (State# t -> INT32 -> r) -> r
+composes2slli :: (State# s -> (# State# t, INT64 #)) -> State# s -> (State# t -> INT64 -> r) -> r
+composes2sllw :: (State# s -> (# State# t, WORD64 #)) -> State# s -> (State# t -> WORD64 -> r) -> r
+composes2slw :: (State# s -> (# State# t, WORD32 #)) -> State# s -> (State# t -> WORD32 -> r) -> r
+composes2sMa :: (State# s -> (# State# t, MutableArray# u e #)) -> State# s -> (State# t -> MutableArray# u e -> r) -> r
 composes2sMb :: (State# s -> (# State# t, MutableByteArray# u #)) -> State# s -> (State# t -> MutableByteArray# u -> r) -> r
-composes2sMv :: (State# s -> (# State# t, MVar# u a #)) -> State# s -> (State# t -> MVar# u a -> r) -> r
+composes2sMv :: (State# s -> (# State# t, MVar# u e #)) -> State# s -> (State# t -> MVar# u e -> r) -> r
 composes2so :: (State# s -> (# State# t, BCO# #)) -> State# s -> (State# t -> BCO# -> r) -> r
 composes2sp :: (State# s -> (# State# t, Addr# #)) -> State# s -> (State# t -> Addr# -> r) -> r
+composes2sSn :: (State# s -> (# State# t, StableName# a #)) -> State# s -> (State# t -> StableName# a -> r) -> r
+composes2sSp :: (State# s -> (# State# t, StablePtr# a #)) -> State# s -> (State# t -> StablePtr# a -> r) -> r
 composes2st :: (State# s -> (# State# t, ThreadId# #)) -> State# s -> (State# t -> ThreadId# -> r) -> r
-composes2sTv :: (State# s -> (# State# t, TVar# u a #)) -> State# s -> (State# t -> TVar# u a -> r) -> r
-composes2sv :: (State# s -> (# State# t, MutVar# u a #)) -> State# s -> (State# t -> MutVar# u a -> r) -> r
+composes2sTv :: (State# s -> (# State# t, TVar# u e #)) -> State# s -> (State# t -> TVar# u e -> r) -> r
+composes2sv :: (State# s -> (# State# t, MutVar# u e #)) -> State# s -> (State# t -> MutVar# u e -> r) -> r
 composes2sw :: (State# s -> (# State# t, Word# #)) -> State# s -> (State# t -> Word# -> r) -> r
 composes2sWp :: (State# s -> (# State# t, Weak# a #)) -> State# s -> (State# t -> Weak# a -> r) -> r
+composew2ib :: (Word# -> (# Int#, ByteArray# #)) -> Word# -> (Int# -> ByteArray# -> r) -> r
 composew2wi :: (Word# -> (# Word#, Int# #)) -> Word# -> (Word# -> Int# -> r) -> r
 composew2ww :: (Word# -> (# Word#, Word# #)) -> Word# -> (Word# -> Word# -> r) -> r
-compose_3pab :: (a -> (# Addr#, Array# b, ByteArray# #)) -> a -> (Addr# -> Array# b -> ByteArray# -> r) -> r
-compose_3pba :: (a -> (# Addr#, ByteArray#, Array# b #)) -> a -> (Addr# -> ByteArray# -> Array# b -> r) -> r
+compose_3pab :: (a -> (# Addr#, Array# e, ByteArray# #)) -> a -> (Addr# -> Array# e -> ByteArray# -> r) -> r
+compose_3pba :: (a -> (# Addr#, ByteArray#, Array# e #)) -> a -> (Addr# -> ByteArray# -> Array# e -> r) -> r
+composed3iib :: (Double# -> (# Int#, Int#, ByteArray# #)) -> Double# -> (Int# -> Int# -> ByteArray# -> r) -> r
+composed3iii :: (Double# -> (# Int#, Int#, Int# #)) -> Double# -> (Int# -> Int# -> Int# -> r) -> r
+composef3iib :: (Float# -> (# Int#, Int#, ByteArray# #)) -> Float# -> (Int# -> Int# -> ByteArray# -> r) -> r
+composei3iii :: (Int# -> (# Int#, Int#, Int# #)) -> Int# -> (Int# -> Int# -> Int# -> r) -> r
+composes3s__ :: (State# s -> (# State# t, a, b #)) -> State# s -> (State# t -> a -> b -> r) -> r
+composes3s_2__ :: (State# s -> (# State# t, a, (# b, c #) #)) -> State# s -> (State# t -> a -> b -> c -> r) -> r
+composes3sCp :: (State# s -> (# State# t, Compact#, Addr# #)) -> State# s -> (State# t -> Compact# -> Addr# -> r) -> r
+composes3sii :: (State# s -> (# State# t, Int#, Int# #)) -> State# s -> (State# t -> Int# -> Int# -> r) -> r
 composes3si_ :: (State# s -> (# State# t, Int#, a #)) -> State# s -> (State# t -> Int# -> a -> r) -> r
 composes3spw :: (State# s -> (# State# t, Addr#, Word# #)) -> State# s -> (State# t -> Addr# -> Word# -> r) -> r
+composeb4ibib :: (ByteArray# -> (# Int#, ByteArray#, Int#, ByteArray# #)) -> ByteArray# -> (Int# -> ByteArray# -> Int# -> ByteArray# -> r) -> r
 composed4iwwi :: (Double# -> (# Int#, Word#, Word#, Int# #)) -> Double# -> (Int# -> Word# -> Word# -> Int# -> r) -> r
 composes4siii :: (State# s -> (# State# t, Int#, Int#, Int# #)) -> State# s -> (State# t -> Int# -> Int# -> Int# -> r) -> r
-composea1_ p x f = case p x of (# a #) -> f a
-composei1_ p x f = case p x of (# a #) -> f a
-composeo1_ p x f = case p x of (# a #) -> f a
-composed2ii p x f = case p x of (# a, b #) -> f a b
-composef2ii p x f = case p x of (# a, b #) -> f a b
-composei2i_ p x f = case p x of (# a, b #) -> f a b
-composei2ii p x f = case p x of (# a, b #) -> f a b
-composes2s_ p x f = case p x of (# a, b #) -> f a b
-composes2sa p x f = case p x of (# a, b #) -> f a b
-composes2sAa p x f = case p x of (# a, b #) -> f a b
-composes2sb p x f = case p x of (# a, b #) -> f a b
-composes2sc p x f = case p x of (# a, b #) -> f a b
-composes2sd p x f = case p x of (# a, b #) -> f a b
-composes2sf p x f = case p x of (# a, b #) -> f a b
-composes2si p x f = case p x of (# a, b #) -> f a b
-composes2sSa p x f = case p x of (# a, b #) -> f a b
-composes2sSMa p x f = case p x of (# a, b #) -> f a b
-composes2sSn p x f = case p x of (# a, b #) -> f a b
-composes2sSp p x f = case p x of (# a, b #) -> f a b
-composes2sMa p x f = case p x of (# a, b #) -> f a b
-composes2sMAa p x f = case p x of (# a, b #) -> f a b
-composes2sMb p x f = case p x of (# a, b #) -> f a b
-composes2sMv p x f = case p x of (# a, b #) -> f a b
-composes2so p x f = case p x of (# a, b #) -> f a b
-composes2sp p x f = case p x of (# a, b #) -> f a b
-composes2st p x f = case p x of (# a, b #) -> f a b
-composes2sTv p x f = case p x of (# a, b #) -> f a b
-composes2sv p x f = case p x of (# a, b #) -> f a b
-composes2sw p x f = case p x of (# a, b #) -> f a b
-composes2sWp p x f = case p x of (# a, b #) -> f a b
-composew2wi p x f = case p x of (# a, b #) -> f a b
-composew2ww p x f = case p x of (# a, b #) -> f a b
-compose_3pab p x f = case p x of (# a, b, c #) -> f a b c
-compose_3pba p x f = case p x of (# a, b, c #) -> f a b c
-composes3si_ p x f = case p x of (# a, b, c #) -> f a b c
-composes3spw p x f = case p x of (# a, b, c #) -> f a b c
-composed4iwwi p x f = case p x of (# a, b, c, d #) -> f a b c d
-composes4siii p x f = case p x of (# a, b, c, d #) -> f a b c d
 
+compose_1_ f x k = case f x of (# a #) -> k a
+composei1_ f x k = case f x of (# a #) -> k a
+composeo1_ f x k = case f x of (# a #) -> k a
+composep1_ f x k = case f x of (# a #) -> k a
+composew1_ f x k = case f x of (# a #) -> k a
+compose_2ab f x k = case f x of (# a, b #) -> k a b
+composeb2ib f x k = case f x of (# a, b #) -> k a b
+composed2ii f x k = case f x of (# a, b #) -> k a b
+composed2llii f x k = case f x of (# a, b #) -> k a b
+composef2ii f x k = case f x of (# a, b #) -> k a b
+composehhi2hhihhi f x k = case f x of (# a, b #) -> k a b
+composehhw2hhwhhw f x k = case f x of (# a, b #) -> k a b
+composehi2hihi f x k = case f x of (# a, b #) -> k a b
+composehw2hwhw f x k = case f x of (# a, b #) -> k a b
+composei2i_ f x k = case f x of (# a, b #) -> k a b
+composei2ib f x k = case f x of (# a, b #) -> k a b
+composei2ii f x k = case f x of (# a, b #) -> k a b
+composeli2ib f x k = case f x of (# a, b #) -> k a b
+composelli2ib f x k = case f x of (# a, b #) -> k a b
+composellw2ib f x k = case f x of (# a, b #) -> k a b
+composelw2ib f x k = case f x of (# a, b #) -> k a b
+composep2ib f x k = case f x of (# a, b #) -> k a b
+composes2s_ f x k = case f x of (# a, b #) -> k a b
+composes2sa f x k = case f x of (# a, b #) -> k a b
+composes2sb f x k = case f x of (# a, b #) -> k a b
+composes2sC f x k = case f x of (# a, b #) -> k a b
+composes2sc f x k = case f x of (# a, b #) -> k a b
+composes2sd f x k = case f x of (# a, b #) -> k a b
+composes2sf f x k = case f x of (# a, b #) -> k a b
+composes2si f x k = case f x of (# a, b #) -> k a b
+composes2sli f x k = case f x of (# a, b #) -> k a b
+composes2slli f x k = case f x of (# a, b #) -> k a b
+composes2sllw f x k = case f x of (# a, b #) -> k a b
+composes2slw f x k = case f x of (# a, b #) -> k a b
+composes2sMa f x k = case f x of (# a, b #) -> k a b
+composes2sMb f x k = case f x of (# a, b #) -> k a b
+composes2sMv f x k = case f x of (# a, b #) -> k a b
+composes2so f x k = case f x of (# a, b #) -> k a b
+composes2sp f x k = case f x of (# a, b #) -> k a b
+composes2sSn f x k = case f x of (# a, b #) -> k a b
+composes2sSp f x k = case f x of (# a, b #) -> k a b
+composes2st f x k = case f x of (# a, b #) -> k a b
+composes2sTv f x k = case f x of (# a, b #) -> k a b
+composes2sv f x k = case f x of (# a, b #) -> k a b
+composes2sw f x k = case f x of (# a, b #) -> k a b
+composes2sWp f x k = case f x of (# a, b #) -> k a b
+composew2ib f x k = case f x of (# a, b #) -> k a b
+composew2wi f x k = case f x of (# a, b #) -> k a b
+composew2ww f x k = case f x of (# a, b #) -> k a b
+compose_3pab f x k = case f x of (# a, b, c #) -> k a b c
+compose_3pba f x k = case f x of (# a, b, c #) -> k a b c
+composed3iib f x k = case f x of (# a, b, c #) -> k a b c
+composed3iii f x k = case f x of (# a, b, c #) -> k a b c
+composef3iib f x k = case f x of (# a, b, c #) -> k a b c
+composei3iii f x k = case f x of (# a, b, c #) -> k a b c
+composes3s__ f x k = case f x of (# a, b, c #) -> k a b c
+composes3s_2__ f x k = case f x of (# a, b, (# c, d #) #) -> k a b c d
+composes3sCp f x k = case f x of (# a, b, c #) -> k a b c
+composes3sii f x k = case f x of (# a, b, c #) -> k a b c
+composes3si_ f x k = case f x of (# a, b, c #) -> k a b c
+composes3spw f x k = case f x of (# a, b, c #) -> k a b c
+composeb4ibib f x k = case f x of (# a, b, c, d #) -> k a b c d
+composed4iwwi f x k = case f x of (# a, b, c, d #) -> k a b c d
+composes4siii f x k = case f x of (# a, b, c, d #) -> k a b c d
+
+#if __GLASGOW_HASKELL__ >= 710
+composes2sSa :: (State# s -> (# State# t, SmallArray# e #)) -> State# s -> (State# t -> SmallArray# e -> r) -> r
+composes2sSMa :: (State# s -> (# State# t, SmallMutableArray# u e #)) -> State# s -> (State# t -> SmallMutableArray# u e -> r) -> r
+composes2sSa f x k = case f x of (# a, b #) -> k a b
+composes2sSMa f x k = case f x of (# a, b #) -> k a b
+#endif
+#if __GLASGOW_HASKELL__ >= 704
+composes2sAa :: (State# s -> (# State# t, ArrayArray# #)) -> State# s -> (State# t -> ArrayArray# -> r) -> r
+composes2sMAa :: (State# s -> (# State# t, MutableArrayArray# u #)) -> State# s -> (State# t -> MutableArrayArray# u -> r) -> r
+composes2sAa f x k = case f x of (# a, b #) -> k a b
+composes2sMAa f x k = case f x of (# a, b #) -> k a b
+#endif
+
 -- | This is an \"inverse\" of 'composes2s_' because sometimes it might be
 -- useful to produce a @'State#' s a -> (\# 'State#' s, a \#)@ of your own.
 -- Example:
 -- 
 -- @returnIO x = 'IO' ('decomposes2s_' (\s r -> r s x))@
-decomposes2s_ :: (State# s -> (State# s -> a -> (# State# s, a #)) -> (# State# s, a #)) -> State# s -> (# State# s, a #)
+decomposes2s_ :: (State# s -> (State# t -> a -> (# State# t, a #)) -> (# State# t, a #)) -> State# s -> (# State# t, a #)
 decomposes2s_ f x = f x (\a b -> (# a, b #))
+
+decompose_2__ :: (a -> (b -> c -> (# b, c #)) -> (# b, c #)) -> a -> (# b, c #)
+decompose_2__ f x = f x (\a b -> (# a, b #))
diff --git a/src/Data/Tuple/Unboxed/Rep.hs b/src/Data/Tuple/Unboxed/Rep.hs
new file mode 100644
--- /dev/null
+++ b/src/Data/Tuple/Unboxed/Rep.hs
@@ -0,0 +1,250 @@
+{-# LANGUAGE UnboxedTuples, MagicHash, CPP #-}
+#if __GLASGOW_HASKELL__ >= 800
+{-# LANGUAGE TypeInType, RankNTypes, MultiParamTypeClasses, FlexibleInstances #-}
+{-# OPTIONS_GHC -fobject-code #-}
+
+-------------------------------------------------------------------------------
+-- |
+-- Module      : Data.Tuple.Unboxed.Rep
+-- Copyright   : (C) 2020 mniip
+-- License     : MIT
+-- Maintainer  : mniip <mniip@mniip.com>
+-- Stability   : experimental
+-- Portability : non-portable
+--
+-- This module provides an ad-hoc polymorphic alternative to the functions in 
+-- "Data.Tuple.Unboxed". The functions have the same basic signature, but using
+-- GHC 8.0+ features they are made parametrically polymorphic within each fixed
+-- representation/calling convention.
+--
+-- This module defines instances for all calling conventions that have ever come
+-- up in "GHC.Prim" but in principle other cases could be added too.
+-------------------------------------------------------------------------------
+module Data.Tuple.Unboxed.Rep
+  ( RepCompose1(..)
+  , RepCompose2(..)
+  , RepCompose3(..)
+  , RepCompose4(..)
+  ) where
+
+import GHC.Prim
+import GHC.Exts
+
+#if __GLASGOW_HASKELL__ >= 802
+type VoidRep = TupleRep '[]
+#endif
+
+#if __GLASGOW_HASKELL__ < 802
+type LiftedRep = PtrRepLifted
+type UnlfitedRep = PtrRepUnlifted
+#endif
+
+class RepCompose1 (r0 :: RuntimeRep) (r1 :: RuntimeRep) where
+  repCompose1 :: forall (a :: TYPE r0) (b :: TYPE r1) (r :: *). (a -> (# b #)) -> a -> (b -> r) -> r
+  repDecompose1 :: forall (a :: TYPE r0) (b :: TYPE r1) (r :: *). (a -> (b -> (# b #)) -> (# b #)) -> a -> (# b #)
+
+class RepCompose2 (r0 :: RuntimeRep) (r1 :: RuntimeRep) (r2 :: RuntimeRep) where
+  repCompose2 :: forall (a :: TYPE r0) (b :: TYPE r1) (c :: TYPE r2) (r :: *). (a -> (# b, c #)) -> a -> (b -> c -> r) -> r
+  repDecompose2 :: forall (a :: TYPE r0) (b :: TYPE r1) (c :: TYPE r2) (r :: *). (a -> (b -> c -> (# b, c #)) -> (# b, c #)) -> a -> (# b, c #)
+
+class RepCompose3 (r0 :: RuntimeRep) (r1 :: RuntimeRep) (r2 :: RuntimeRep) (r3 :: RuntimeRep) where
+  repCompose3 :: forall (a :: TYPE r0) (b :: TYPE r1) (c :: TYPE r2) (d :: TYPE r3) (r :: *). (a -> (# b, c, d #)) -> a -> (b -> c -> d -> r) -> r
+  repDecompose3 :: forall (a :: TYPE r0) (b :: TYPE r1) (c :: TYPE r2) (d :: TYPE r3) (r :: *). (a -> (b -> c -> d -> (# b, c, d #)) -> (# b, c, d #)) -> a -> (# b, c, d #)
+
+class RepCompose4 (r0 :: RuntimeRep) (r1 :: RuntimeRep) (r2 :: RuntimeRep) (r3 :: RuntimeRep) (r4 :: RuntimeRep) where
+  repCompose4 :: forall (a :: TYPE r0) (b :: TYPE r1) (c :: TYPE r2) (d :: TYPE r3) (e :: TYPE r4) (r :: *). (a -> (# b, c, d, e #)) -> a -> (b -> c -> d -> e -> r) -> r
+  repDecompose4 :: forall (a :: TYPE r0) (b :: TYPE r1) (c :: TYPE r2) (d :: TYPE r3) (e :: TYPE r4) (r :: *). (a -> (b -> c -> d -> e -> (# b, c, d, e #)) -> (# b, c, d, e #)) -> a -> (# b, c, d, e #)
+
+instance RepCompose1 LiftedRep LiftedRep where
+  repCompose1 f x k = case f x of (# a #) -> k a
+  repDecompose1 f x = f x (\a -> (# a #))
+
+instance RepCompose1 UnliftedRep LiftedRep where
+  repCompose1 f x k = case f x of (# a #) -> k a
+  repDecompose1 f x = f x (\a -> (# a #))
+
+instance RepCompose1 IntRep LiftedRep where
+  repCompose1 f x k = case f x of (# a #) -> k a
+  repDecompose1 f x = f x (\a -> (# a #))
+
+instance RepCompose1 WordRep LiftedRep where
+  repCompose1 f x k = case f x of (# a #) -> k a
+  repDecompose1 f x = f x (\a -> (# a #))
+
+instance RepCompose1 AddrRep LiftedRep where
+  repCompose1 f x k = case f x of (# a #) -> k a
+  repDecompose1 f x = f x (\a -> (# a #))
+
+instance RepCompose2 VoidRep VoidRep LiftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 VoidRep VoidRep UnliftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 VoidRep VoidRep IntRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 VoidRep VoidRep WordRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 VoidRep VoidRep AddrRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 VoidRep VoidRep FloatRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 VoidRep VoidRep DoubleRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 LiftedRep UnliftedRep UnliftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 UnliftedRep IntRep UnliftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 IntRep IntRep LiftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 IntRep IntRep UnliftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 IntRep IntRep IntRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 WordRep IntRep UnliftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 WordRep WordRep IntRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 WordRep WordRep WordRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 AddrRep IntRep UnliftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 FloatRep IntRep IntRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 DoubleRep IntRep IntRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose3 VoidRep VoidRep LiftedRep LiftedRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 VoidRep VoidRep UnliftedRep AddrRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 VoidRep VoidRep IntRep LiftedRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 VoidRep VoidRep IntRep IntRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 VoidRep VoidRep AddrRep WordRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 LiftedRep AddrRep UnliftedRep UnliftedRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 IntRep IntRep IntRep IntRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 FloatRep IntRep IntRep UnliftedRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 DoubleRep IntRep IntRep UnliftedRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose3 DoubleRep IntRep IntRep IntRep where
+  repCompose3 f x k = case f x of (# a, b, c #) -> k a b c
+  repDecompose3 f x = f x (\a b c -> (# a, b, c #))
+
+instance RepCompose4 VoidRep VoidRep IntRep IntRep IntRep where
+  repCompose4 f x k = case f x of (# a, b, c, d #) -> k a b c d
+  repDecompose4 f x = f x (\a b c d -> (# a, b, c, d #))
+
+instance RepCompose4 UnliftedRep IntRep UnliftedRep IntRep UnliftedRep where
+  repCompose4 f x k = case f x of (# a, b, c, d #) -> k a b c d
+  repDecompose4 f x = f x (\a b c d -> (# a, b, c, d #))
+
+instance RepCompose4 DoubleRep IntRep WordRep WordRep IntRep where
+  repCompose4 f x k = case f x of (# a, b, c, d #) -> k a b c d
+  repDecompose4 f x = f x (\a b c d -> (# a, b, c, d #))
+
+#if __GLASGOW_HASKELL__ >= 808
+instance RepCompose2 VoidRep VoidRep Int64Rep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 VoidRep VoidRep Word64Rep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 Int8Rep Int8Rep Int8Rep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 Int16Rep Int16Rep Int16Rep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 Int64Rep IntRep UnliftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 Int64Rep Int64Rep Int64Rep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 Word8Rep Word8Rep Word8Rep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 Word16Rep Word16Rep Word16Rep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 Word64Rep IntRep UnliftedRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 Word64Rep Word64Rep Word64Rep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+
+instance RepCompose2 DoubleRep Int64Rep IntRep where
+  repCompose2 f x k = case f x of (# a, b #) -> k a b
+  repDecompose2 f x = f x (\a b -> (# a, b #))
+#endif
+
+#else
+module Data.Tuple.Unboxed.Rep () where
+#endif
