diff --git a/Biobase/Turner.hs b/Biobase/Turner.hs
--- a/Biobase/Turner.hs
+++ b/Biobase/Turner.hs
@@ -1,3 +1,4 @@
+{-# LANGUAGE TypeOperators #-}
 
 -- | The 'Turner2004' data structure reflects the RNA (and DNA) energy
 -- parameters known as the Turner 2004 data set.
@@ -10,41 +11,48 @@
 
 import Data.ByteString
 import Data.Map as M
+import Data.Array.Repa.Index
 
 import Biobase.Primary
 import Biobase.Secondary
 import Data.PrimitiveArray
-import Data.PrimitiveArray.Ix
+import Data.PrimitiveArray.Unboxed
 
 -- | The parameters. Turner parameters are set by the Import module for
 -- nucleotides n,a,c,g,u. All values that are not read (or are ".") will end up
 -- with a value > 100K.
 --
--- [1] Yes, such instances are easily created, but I don't want to pull in
--- another library and I don't want to create an Ix instance here.
---
 -- TODO use 'Energy' instead of 'Double'
+--
+-- TODO specialized shape types for pairs?
 
+type PP = (Z:.Nuc:.Nuc:.Nuc:.Nuc)
+type PN = (Z:.Nuc:.Nuc:.Nuc)
+type PNN = (Z:.Nuc:.Nuc:.Nuc:.Nuc)
+type PPNN = PP:.Nuc:.Nuc
+type PPNNN = PPNN:.Nuc
+type PPNNNN = PPNNN:.Nuc
+
 data Turner2004 = Turner2004
-  { stack :: PrimArray (Pair,Pair) Double
+  { stack :: PrimArray PP Double
   , dangle3 :: PrimArray PN Double
   , dangle5 :: PrimArray PN Double
-  , hairpinL :: PrimArray Int Double
+  , hairpinL :: PrimArray DIM1 Double
   , hairpinMM :: PrimArray PNN Double
   , hairpinLookup :: M.Map ByteString Double
   , hairpinGGG :: Double
   , hairpinCslope :: Double
   , hairpinCintercept :: Double
   , hairpinC3 :: Double
-  , bulgeL :: PrimArray Int Double
+  , bulgeL :: PrimArray DIM1 Double
   , bulgeSingleC :: Double
-  , iloop1x1 :: PrimArray (Pair,Pair,(Nuc,Nuc)) Double
-  , iloop2x1 :: PrimArray (Pair,Pair,(Nuc,Nuc,Nuc)) Double
-  , iloop2x2 :: PrimArray (Pair,Pair,(Nuc,Nuc,Nuc,Nuc)) Double -- yeah, 6-tuple ix instances :-( [1]
+  , iloop1x1 :: PrimArray PPNN Double
+  , iloop2x1 :: PrimArray PPNNN Double
+  , iloop2x2 :: PrimArray PPNNNN Double
   , iloopMM :: PrimArray PNN Double
   , iloop2x3MM :: PrimArray PNN Double
   , iloop1xnMM :: PrimArray PNN Double
-  , iloopL :: PrimArray Int Double
+  , iloopL :: PrimArray DIM1 Double
   , multiMM :: PrimArray PNN Double
   , ninio :: Double
   , maxNinio :: Double
@@ -54,13 +62,11 @@
   , multiAsym :: Double
   , multiStrain :: Double
   , extMM :: PrimArray PNN Double
-  , coaxial :: PrimArray (Pair,Pair) Double -- no intervening unpaired nucleotides
+  , coaxial :: PrimArray PP Double -- no intervening unpaired nucleotides
   , coaxStack :: PrimArray PNN Double
   , tStackCoax :: PrimArray PNN Double
   , largeLoop :: Double
   , termAU :: Double
   , intermolecularInit :: Double
-  } deriving (Read,Show)
+  } deriving (Show)
 
-type PNN = (Pair,Nuc,Nuc)
-type PN  = (Pair,Nuc)
diff --git a/Biobase/Turner/Import.hs b/Biobase/Turner/Import.hs
--- a/Biobase/Turner/Import.hs
+++ b/Biobase/Turner/Import.hs
@@ -1,3 +1,5 @@
+{-# LANGUAGE PatternGuards #-}
+{-# LANGUAGE TupleSections #-}
 {-# LANGUAGE NoMonomorphismRestriction #-}
 {-# LANGUAGE OverloadedStrings #-}
 
@@ -46,6 +48,7 @@
 import qualified Data.List as L
 import System.FilePath.Posix
 import Data.Maybe (fromJust)
+import Data.Array.Repa.Index
 
 import Biobase.Primary
 import Biobase.Secondary
@@ -83,17 +86,17 @@
   cstack'     <- blockFromFile $ fp </> prefix ++ "coaxstack" <.> suffix
   tstack'     <- blockFromFile $ fp </> prefix ++ "tstackcoax" <.> suffix
   return Turner2004
-    { stack         = fromAssocs minPP  maxPP  infE $ L.zip keysPP  stack'
-    , dangle3       = fromAssocs minPB  maxPB  infE $ L.zip keysPB  dangle3'
-    , dangle5       = fromAssocs minPB  maxPB  infE $ L.zip keysPB  dangle5'
-    , hairpinL      = fromAssocs 0      30     infE $ L.zip [1..30] hairpinL'
+    { stack         = fromAssocs minPP  maxPP   infE $ L.zip keysPP  stack'
+    , dangle3       = fromAssocs minPB  maxPB   infE $ L.zip keysPB  dangle3'
+    , dangle5       = fromAssocs minPB  maxPB   infE $ L.zip keysPB  dangle5'
+    , hairpinL      = fromAssocs (Z:.0) (Z:.30) infE $ L.zip d1_30 hairpinL'
     , hairpinMM     = fromAssocs minPBB maxPBB infE $ L.zip keysPBB hairpinMM'
     , hairpinLookup = M.fromList $ hairpinLk3 ++ hairpinLk4 ++ hairpinLk6
     , hairpinGGG    = L.head $ imisc' !! 8
     , hairpinCslope = L.head $ imisc' !! 9
     , hairpinCintercept = L.head $ imisc' !! 10
     , hairpinC3     = L.head $ imisc' !! 11
-    , bulgeL        = fromAssocs 0      30     infE $ L.zip [1..30] bulgeL'
+    , bulgeL        = fromAssocs (Z:.0)      (Z:.30)     infE $ L.zip d1_30 bulgeL'
     , bulgeSingleC  = L.head $ imisc' !! 13
     , iloop1x1      = fromAssocs minPPBB   maxPPBB   infE $ L.zip keysPPBB   iloop1x1'
     , iloop2x1      = fromAssocs minPPBBB  maxPPBBB  infE $ L.zip keysPPBBB  iloop2x1'
@@ -101,7 +104,7 @@
     , iloopMM       = fromAssocs minPBB    maxPBB    infE $ L.zip keysPBB    iloopMM'
     , iloop2x3MM    = fromAssocs minPBB    maxPBB    infE $ L.zip keysPBB    iloop2x3MM'
     , iloop1xnMM    = fromAssocs minPBB    maxPBB    infE $ L.zip keysPBB    iloop1xnMM'
-    , iloopL        = fromAssocs 0      30     infE $ L.zip [1..30] iloopL'
+    , iloopL        = fromAssocs (Z:.0)    (Z:.30)   infE $ L.zip d1_30      iloopL'
     , multiMM       = fromAssocs minPBB    maxPBB    infE $ L.zip keysPBB    multiMM'
     , ninio = L.head $ imisc' !! 2
     , maxNinio = L.head $ imisc' !! 1
@@ -119,32 +122,34 @@
     , intermolecularInit = L.head $ imisc' !! 12
     }
 
-minPP     = (minP,minP)
-maxPP     = (maxP,maxP)
-minP      = (nN,nN)
-maxP      = (nU,nU)
-minPB     = (minP,nN)
-maxPB     = (maxP,nU)
-minPBB    = (minP,nN,nN)
-maxPBB    = (maxP,nU,nU)
-minPPBB   = (minP,minP,(nN,nN))
-maxPPBB   = (maxP,maxP,(nU,nU))
-minPPBBB  = (minP,minP,(nN,nN,nN))
-maxPPBBB  = (maxP,maxP,(nU,nU,nU))
-minPPBBBB = (minP,minP,(nN,nN,nN,nN))
-maxPPBBBB = (maxP,maxP,(nU,nU,nU,nU))
+minPP     = Z:.nN:.nN:.nN:.nN -- (minP,minP)
+maxPP     = Z:.nU:.nU:.nU:.nU -- (maxP,maxP)
+minP      = Z:.nN:.nN -- (nN,nN)
+maxP      = Z:.nU:.nU -- (nU,nU)
+minPB     = minP:.nN -- (minP,nN)
+maxPB     = maxP:.nU -- (maxP,nU)
+minPBB    = minPB:.nN -- (minP,nN,nN)
+maxPBB    = maxPB:.nU -- (maxP,nU,nU)
+minPPBB   = minPP:.nN:.nN -- (minP,minP,(nN,nN))
+maxPPBB   = maxPP:.nU:.nU -- (maxP,maxP,(nU,nU))
+minPPBBB  = minPPBB:.nN -- (minP,minP,(nN,nN,nN))
+maxPPBBB  = maxPPBB:.nU -- (maxP,maxP,(nU,nU,nU))
+minPPBBBB = minPPBBB:.nN -- (minP,minP,(nN,nN,nN,nN))
+maxPPBBBB = maxPPBBB:.nU -- (maxP,maxP,(nU,nU,nU,nU))
 
-keysPP     = [((k1,k2),(k4,k3)) | k1 <- acgu, k3 <- acgu, k2 <- acgu, k4 <- acgu]
-keysPB     = [((k1,k2),k3) | k1 <- acgu, k2 <- acgu, k3 <- acgu]
-keysPBB    = [ ((k1,k2),k3,k4)
+d1_30 = L.map (Z:.) [1..30]
+
+keysPP     = [{- ((k1,k2),(k4,k3)) -} Z:.k1:.k2:.k4:.k3 | k1 <- acgu, k3 <- acgu, k2 <- acgu, k4 <- acgu]
+keysPB     = [{- ((k1,k2),k3) -} Z:.k1:.k2:.k3 | k1 <- acgu, k2 <- acgu, k3 <- acgu]
+keysPBB    = [ {- ((k1,k2),k3,k4) -} Z:.k1:.k2:.k3:.k4
              | k1 <- acgu, k3 <- acgu, k2 <- acgu, k4 <- acgu]
-keysPPBB   = [ ((k1,k2),(k4,k3),(k5,k6))
+keysPPBB   = [ {- ((k1,k2),(k4,k3),(k5,k6)) -} Z:.k1:.k2:.k4:.k3:.k5:.k6
              | (k1,k2) <- plist11, k5 <- acgu, (k3,k4) <- plist11, k6 <- acgu]
-keysPPBBB  = [ ((k1,k2),(k4,k3),(k5,k6,k7))
+keysPPBBB  = [ {- ((k1,k2),(k4,k3),(k5,k6,k7)) -} Z:.k1:.k2:.k4:.k3:.k5:.k6:.k7
              | (k1,k2) <- plist11, k6 <- acgu, k5 <- acgu, (k3,k4) <- plist11, k7 <- acgu]
-keysPPBBBBrna = [ ((k1,k2),(k4,k3),(k5,k6,k7,k8))
+keysPPBBBBrna = [ {- ((k1,k2),(k4,k3),(k5,k6,k7,k8)) -} Z:.k1:.k2:.k4:.k3:.k5:.k6:.k7:.k8
                 | (k1,k2) <- plist22rna, (k3,k4) <- plist22rna, k5 <- acgu, k8 <- acgu, k6 <- acgu, k7 <- acgu]
-keysPPBBBBdna = [ ((k1,k2),(k4,k3),(k5,k6,k7,k8))
+keysPPBBBBdna = [ {- ((k1,k2),(k4,k3),(k5,k6,k7,k8)) -} Z:.k1:.k2:.k4:.k3:.k5:.k6:.k7:.k8
                 | (k1,k2) <- plist22dna, (k3,k4) <- plist22dna, k5 <- acgu, k8 <- acgu, k6 <- acgu, k7 <- acgu]
 
 plist11 = [(nA,nU),(nC,nG),(nG,nC),(nU,nA),(nG,nU),(nU,nG)]
diff --git a/BiobaseTurner.cabal b/BiobaseTurner.cabal
--- a/BiobaseTurner.cabal
+++ b/BiobaseTurner.cabal
@@ -1,9 +1,9 @@
 name:           BiobaseTurner
-version:        0.1.1.0
+version:        0.2.0.0
 author:         Christian Hoener zu Siederdissen
 maintainer:     choener@tbi.univie.ac.at
 homepage:       http://www.tbi.univie.ac.at/~choener/
-copyright:      Christian Hoener zu Siederdissen, 2010,2011
+copyright:      Christian Hoener zu Siederdissen, 2010-2012
 category:       Bioinformatics
 synopsis:       Import Turner RNA parameters
 license:        GPL-3
@@ -26,6 +26,10 @@
                 enumerations, which we handle rather... simplistically. We
                 cannot fix one asymmetry case in dnastack.dh, as we do not
                 change sources.
+                .
+                BIG FAT WARNING indexing now depends on repa shapes and index
+                representations. (with a good reason coming soon). For now,
+                just assume that this has performance benefits.
 
 library
   build-depends:
@@ -36,13 +40,19 @@
     filepath,
     iteratee,
     split,
-    BiobaseXNA,
-    PrimitiveArray
+    BiobaseXNA >= 0.6.0.0,
+    vector >= 0.9,
+    repa >= 2.0,
+    PrimitiveArray >= 0.1.1.2
 
   exposed-modules:
     Biobase.Turner
     Biobase.Turner.Import
 
   ghc-options:
-    -O2
+    -Odph -funbox-strict-fields -fspec-constr
+
+source-repository head
+  type: git
+  location: git://github.com/choener/BiobaseTurner
 
