diff --git a/Biobase/Primary/AA.hs b/Biobase/Primary/AA.hs
--- a/Biobase/Primary/AA.hs
+++ b/Biobase/Primary/AA.hs
@@ -30,43 +30,44 @@
 import qualified Data.Vector.Unboxed as VU
 import qualified GHC.Exts as GHC
 
-import           Biobase.Types.BioSequence
+import Biobase.Types.BioSequence
+import Data.Info
 
 import           Biobase.Primary.Letter
 
 
 
-pattern  Stop   = Letter  0 ∷ Letter AA n
-pattern     A   = Letter  1 ∷ Letter AA n
-pattern     B   = Letter  2 ∷ Letter AA n
-pattern     C   = Letter  3 ∷ Letter AA n
-pattern     D   = Letter  4 ∷ Letter AA n
-pattern     E   = Letter  5 ∷ Letter AA n
-pattern     F   = Letter  6 ∷ Letter AA n
-pattern     G   = Letter  7 ∷ Letter AA n
-pattern     H   = Letter  8 ∷ Letter AA n
-pattern     I   = Letter  9 ∷ Letter AA n
-pattern     K   = Letter 10 ∷ Letter AA n
-pattern     L   = Letter 11 ∷ Letter AA n
-pattern     M   = Letter 12 ∷ Letter AA n
-pattern     N   = Letter 13 ∷ Letter AA n
-pattern     P   = Letter 14 ∷ Letter AA n
-pattern     Q   = Letter 15 ∷ Letter AA n
-pattern     R   = Letter 16 ∷ Letter AA n
-pattern     S   = Letter 17 ∷ Letter AA n
-pattern     T   = Letter 18 ∷ Letter AA n
-pattern     V   = Letter 19 ∷ Letter AA n
-pattern     W   = Letter 20 ∷ Letter AA n
-pattern     X   = Letter 21 ∷ Letter AA n
-pattern     Y   = Letter 22 ∷ Letter AA n
-pattern     Z   = Letter 23 ∷ Letter AA n
-pattern Any     = Letter 24 ∷ Letter AA n
-pattern Unknown = Letter 25 ∷ Letter AA n
-pattern Undef   = Letter 26 ∷ Letter AA n
+pattern  Stop   = Letter  0 :: Letter AA n
+pattern     A   = Letter  1 :: Letter AA n
+pattern     B   = Letter  2 :: Letter AA n
+pattern     C   = Letter  3 :: Letter AA n
+pattern     D   = Letter  4 :: Letter AA n
+pattern     E   = Letter  5 :: Letter AA n
+pattern     F   = Letter  6 :: Letter AA n
+pattern     G   = Letter  7 :: Letter AA n
+pattern     H   = Letter  8 :: Letter AA n
+pattern     I   = Letter  9 :: Letter AA n
+pattern     K   = Letter 10 :: Letter AA n
+pattern     L   = Letter 11 :: Letter AA n
+pattern     M   = Letter 12 :: Letter AA n
+pattern     N   = Letter 13 :: Letter AA n
+pattern     P   = Letter 14 :: Letter AA n
+pattern     Q   = Letter 15 :: Letter AA n
+pattern     R   = Letter 16 :: Letter AA n
+pattern     S   = Letter 17 :: Letter AA n
+pattern     T   = Letter 18 :: Letter AA n
+pattern     V   = Letter 19 :: Letter AA n
+pattern     W   = Letter 20 :: Letter AA n
+pattern     X   = Letter 21 :: Letter AA n
+pattern     Y   = Letter 22 :: Letter AA n
+pattern     Z   = Letter 23 :: Letter AA n
+pattern Any     = Letter 24 :: Letter AA n     -- TODO @Any == X@ supposedly!
+pattern Unknown = Letter 25 :: Letter AA n
+pattern Undef   = Letter 26 :: Letter AA n
 
 -- * Creating functions and aa data.
 
-aa ∷ Int → Letter AA n
+aa :: Int -> Letter AA n
 aa = Letter
 {-# Inline aa #-}
 
@@ -87,24 +88,27 @@
 instance FromJSON (Letter AA n) where
   parseJSON = fmap charLetter . parseJSON
 
---instance (GHC.IsString f) ⇒ ToJSON (Pretty f (Letter AA)) where
+instance Info (Letter AA n) where
+  info = (:[]) . aaChar
+
+--instance (GHC.IsString f) => ToJSON (Pretty f (Letter AA)) where
 --  toJSON = toJSON . T.pack . map letterChar . GHC.toList . getPretty
 
 -- | Translate 'Char' amino acid representation into efficient 'AA' newtype.
 
-charAA ∷ Char → Letter AA n
+charAA :: Char -> Letter AA n
 charAA = B.findWithDefaultL Undef charBaa
 {-# INLINE charAA #-}
 
 -- | 'Char' representation of an 'AA'.
 
-aaChar ∷ Letter AA n → Char
+aaChar :: Letter AA n -> Char
 aaChar = B.findWithDefaultR '?' charBaa
 {-# INLINE aaChar #-}
 
 -- * lookup tables
 
-charBaa ∷ B.Bimap (B.HashMap Char (Letter AA n)) (B.HashMap (Letter AA n) Char)
+charBaa :: B.Bimap (B.HashMap Char (Letter AA n)) (B.HashMap (Letter AA n) Char)
 charBaa = B.fromList
   [ ('*',Stop)
   , ('A',A)
@@ -136,7 +140,7 @@
 
 -- | List of the twenty "default" amino acids. Used, for example, by HMMer.
 
-twentyAA ∷ VU.Vector (Letter AA n)
+twentyAA :: VU.Vector (Letter AA n)
 twentyAA = VU.fromList [ A,C,D,E,F,G,H,I,K,L,M,N,P,Q,R,S,T,V,W,Y ]
 {-# NoInline twentyAA #-}
 
diff --git a/Biobase/Primary/IUPAC.hs b/Biobase/Primary/IUPAC.hs
--- a/Biobase/Primary/IUPAC.hs
+++ b/Biobase/Primary/IUPAC.hs
@@ -11,7 +11,7 @@
 import           Control.Arrow ((***))
 import           Data.ByteString.Char8 (ByteString,unpack)
 import           Data.Char (toUpper)
-import           Data.FileEmbed (embedFile)
+import           Data.FileEmbed (makeRelativeToProject, embedFile)
 import           Data.List (nub,sort)
 import           Data.String
 import           Data.Tuple (swap)
@@ -151,5 +151,5 @@
 -- | Raw iupac data, embedded into the library.
 
 iupacNucleotides :: ByteString
-iupacNucleotides = $(embedFile "sources/iupac-nucleotides")
+iupacNucleotides = $(makeRelativeToProject "sources/iupac-nucleotides" >>= embedFile)
 
diff --git a/Biobase/Primary/Letter.hs b/Biobase/Primary/Letter.hs
--- a/Biobase/Primary/Letter.hs
+++ b/Biobase/Primary/Letter.hs
@@ -27,19 +27,20 @@
 import qualified Data.Vector.Unboxed as VU
 
 import           Data.PrimitiveArray hiding (map)
+import Data.Info
 
 
 
 -- | A 'Letter' together with its phantom type @seqTy@ encodes bio-sequences,
 -- while @nameTy@ allows to specify a type-level name for a letter.
 
-newtype Letter (seqTy ∷ *) (nameTy ∷ k) = Letter { getLetter ∷ Int }
+newtype Letter (seqTy :: *) (nameTy :: k) = Letter { getLetter :: Int }
   deriving (Eq,Ord,Generic,Ix,Typeable)
 
 -- | While @coerce@ will always work, this way restricts the change to just the
 -- @nameTy@.
 
-changeNameTy ∷ Letter seqTy nameTy → Letter seqTy newNameTy
+changeNameTy :: Letter seqTy nameTy -> Letter seqTy newNameTy
 {-# Inline changeNameTy #-}
 changeNameTy = coerce
 
@@ -47,11 +48,11 @@
 -- implementation. This also allows for better use of generic programming
 -- downstream.
 
-instance (Typeable t, Typeable (Letter t n)) ⇒ Data (Letter t n) where
+instance (Typeable t, Typeable (Letter t n)) => Data (Letter t n) where
   toConstr = mkIntegralConstr letterDataType . getLetter
   gunfold _ z c = case constrRep c of
-    (IntConstr x) → z (Letter $ fromIntegral x)
-    _ → errorWithoutStackTrace $ "Biobase.Primary.Letter.gunfold: Constructor "
+    (IntConstr x) -> z (Letter $ fromIntegral x)
+    _ -> errorWithoutStackTrace $ "Biobase.Primary.Letter.gunfold: Constructor "
           ++ show c
           ++ " is not of type Letter (using Int-rep)"
   dataTypeOf _ = letterDataType
@@ -70,31 +71,31 @@
 -- have single-char representations.
 
 class LetterChar t n where
-  letterChar ∷ Letter t n → Char
-  charLetter ∷ Char → Letter t n
+  letterChar :: Letter t n -> Char
+  charLetter :: Char -> Letter t n
 
 -- | Conversion from a large number of sequence-like inputs to primary
 -- sequences.
 
 class MkPrimary c t n where
-    primary ∷ c → Primary t n
+    primary :: c -> Primary t n
 
-instance MkPrimary (VU.Vector Char) t n ⇒ MkPrimary String t n where
+instance MkPrimary (VU.Vector Char) t n => MkPrimary String t n where
     primary = primary . VU.fromList
 
-instance MkPrimary (VU.Vector Char) t n ⇒  MkPrimary T.Text t n where
+instance MkPrimary (VU.Vector Char) t n =>  MkPrimary T.Text t n where
     primary = primary . VU.fromList . T.unpack
 
-instance MkPrimary (VU.Vector Char) t n ⇒ MkPrimary TL.Text t n where
+instance MkPrimary (VU.Vector Char) t n => MkPrimary TL.Text t n where
     primary = primary . VU.fromList . TL.unpack
 
-instance MkPrimary (VU.Vector Char) t n ⇒ MkPrimary BS.ByteString t n where
+instance MkPrimary (VU.Vector Char) t n => MkPrimary BS.ByteString t n where
     primary = primary . VU.fromList . BS.unpack
 
-instance MkPrimary (VU.Vector Char) t n ⇒ MkPrimary BSL.ByteString t n where
+instance MkPrimary (VU.Vector Char) t n => MkPrimary BSL.ByteString t n where
     primary = primary . VU.fromList . BSL.unpack
 
-instance (VU.Unbox (Letter t n), IsString [Letter t n]) ⇒ IsString (VU.Vector (Letter t n)) where
+instance (VU.Unbox (Letter t n), IsString [Letter t n]) => IsString (VU.Vector (Letter t n)) where
     fromString = VU.fromList . fromString
 
 
@@ -102,7 +103,7 @@
 -- *** Instances for 'Letter'.
 
 derivingUnbox "Letter"
-  [t| forall t n . Letter t n → Int |] [| getLetter |] [| Letter |]
+  [t| forall t n . Letter t n -> Int |] [| getLetter |] [| Letter |]
 
 instance Hashable (Letter t n)
 
@@ -114,6 +115,8 @@
   newtype LimitType (Letter l n) = LtLetter (Letter l n)
   linearIndex _ (Letter i) = i
   {-# Inline linearIndex #-}
+  fromLinearIndex _ k = Letter k
+  {-# Inline fromLinearIndex #-}
   size (LtLetter (Letter h)) = h+1
   {-# Inline size #-}
   inBounds (LtLetter h) i = zeroBound <= i && i <= h
@@ -124,15 +127,18 @@
   {-# Inline zeroBound' #-}
   totalSize (LtLetter (Letter k)) = [ fromIntegral k + 1 ]
   {-# Inline totalSize #-}
+  showBound (LtLetter (Letter k)) = [ show k ]
+  showIndex (Letter k) = [ show k ]
 
+deriving instance (Bounded (Letter l n)) => Bounded (LimitType (Letter l n))
 deriving instance Eq      (LimitType (Letter l n))
 deriving instance Generic (LimitType (Letter l n))
-deriving instance (Read (Letter l n)) ⇒ Read    (LimitType (Letter l n))
-deriving instance (Show (Letter l n)) ⇒ Show    (LimitType (Letter l n))
+deriving instance (Read (Letter l n)) => Read    (LimitType (Letter l n))
+deriving instance (Show (Letter l n)) => Show    (LimitType (Letter l n))
 deriving instance Typeable (LimitType (Letter l n))
-deriving instance Data (Letter l n) ⇒ Data (LimitType (Letter l n))
+deriving instance Data (Letter l n) => Data (LimitType (Letter l n))
 
-instance IndexStream z ⇒ IndexStream (z:.Letter l n) where
+instance IndexStream z => IndexStream (z:.Letter l n) where
   streamUp (ls:..LtLetter l) (hs:..LtLetter h) = flatten mk step $ streamUp ls hs
     where mk z = return (z,l)
           step (z,k)
@@ -151,8 +157,8 @@
   {-# Inline streamDown #-}
 
 instance IndexStream (Letter l n) where
-  streamUp l h = map (\(Z:.k) → k) $ streamUp (ZZ:..l) (ZZ:..h)
-  streamDown l h = map (\(Z:.k) → k) $ streamDown (ZZ:..l) (ZZ:..h)
+  streamUp l h = map (\(Z:.k) -> k) $ streamUp (ZZ:..l) (ZZ:..h)
+  streamDown l h = map (\(Z:.k) -> k) $ streamDown (ZZ:..l) (ZZ:..h)
   {-# Inline streamUp #-}
   {-# Inline streamDown #-}
 
diff --git a/Biobase/Primary/Nuc/RNA.hs b/Biobase/Primary/Nuc/RNA.hs
--- a/Biobase/Primary/Nuc/RNA.hs
+++ b/Biobase/Primary/Nuc/RNA.hs
@@ -71,19 +71,20 @@
 acgu = [A .. U]
 
 charRNA = toUpper >>> \case
-    'A' → A
-    'C' → C
-    'G' → G
-    'U' → U
-    _   → N
+    'A' -> A
+    'C' -> C
+    'G' -> G
+    'U' -> U
+    _   -> N
 {-# INLINE charRNA #-}
 
 rnaChar = \case
-  A → 'A'
-  C → 'C'
-  G → 'G'
-  U → 'U'
-  N → 'N'
+  A -> 'A'
+  C -> 'C'
+  G -> 'G'
+  U -> 'U'
+  N -> 'N'
+  _ -> '\9888'
 {-# INLINE rnaChar #-}            
 
 -- | An isomorphism from 'Char' to 'Letter RNA'. This assumes that the
@@ -110,4 +111,8 @@
 
 instance IsString [Letter RNA n] where
     fromString = map charRNA
+
+viennaPairs = [ (C,G), (G,C), (G,U), (U,G), (A,U), (U,A) ]
+viennaPairsNN = viennaPairs ++ [ (N,N) ]
+
 
diff --git a/Biobase/Primary/Trans.hs b/Biobase/Primary/Trans.hs
--- a/Biobase/Primary/Trans.hs
+++ b/Biobase/Primary/Trans.hs
@@ -18,7 +18,6 @@
 import           Control.Lens
 import           Control.Arrow ((***))
 import           Data.ByteString.Char8 (ByteString,unpack)
-import           Data.FileEmbed (embedFile)
 import           Data.Map.Strict (Map)
 import           Data.Tuple (swap)
 import qualified Data.Map.Strict as M
@@ -37,15 +36,15 @@
 
 -- | Transform translation tables into the @Letter DNA/Letter AA@ format.
 
-letterTranslationTable ∷ TranslationTable Char Char → TranslationTable (Letter DNA n) (Letter AA n)
+letterTranslationTable :: TranslationTable Char Char -> TranslationTable (Letter DNA n) (Letter AA n)
 letterTranslationTable tbl = TranslationTable
   { _codonToAminoAcid  = M.fromList . map (ftriplet *** felement) . M.toList $ tbl^.codonToAminoAcid
   , _aminoAcidtoCodons = M.fromList . map (charAA *** map felement) . M.toList $ tbl^.aminoAcidtoCodons
   , _tableID           = tbl^.tableID
   , _tableName         = tbl^.tableName
-  } where ftriplet ∷ Codon Char → Codon (Letter DNA n)
+  } where ftriplet :: Codon Char -> Codon (Letter DNA n)
           ftriplet = over each charDNA
-          felement ∷ TranslationElement Char Char → TranslationElement (Letter DNA n) (Letter AA n)
+          felement :: TranslationElement Char Char -> TranslationElement (Letter DNA n) (Letter AA n)
           felement = over (baseCodon.each) charDNA . over aminoAcid charAA
 
 instance Translation (Codon (Letter DNA n)) where
@@ -54,6 +53,8 @@
   type AAType (Codon (Letter DNA n)) = Letter AA n
   translate tbl t = maybe Unknown _aminoAcid $ M.lookup t (tbl^.codonToAminoAcid)
   {-# Inline translate #-}
+  translateAllFrames = translate
+  {-# Inline translateAllFrames #-}
 
 instance Translation (Primary DNA n) where
   type TargetType (Primary DNA n) = Primary AA n
@@ -64,58 +65,15 @@
   -- TODO we could consider returning @Nothing@ in case the input is not
   -- power-of-three.
   translate tbl xs = VU.unfoldrN (VU.length xs `div` 3) go xs
-    where go (VU.splitAt 3 → (hs,ts))
+    where go (VU.splitAt 3 -> (hs,ts))
             | VU.length hs < 3 = Nothing
             | otherwise        = Just (aa,ts)
             where [a,b,c] = VU.toList hs
                   aa      = translate tbl $ Codon a b c
   {-# Inline translate #-}
-
-
-{-
--- | Using the codon table, create an amino acid sequence from a @DNA@
--- sequence (encoded as 'Primary DNA'). Suffixed @seq@ as we deal with
--- sequences, not letters.
-
-dnaAAseq :: Primary DNA -> Primary AA
-dnaAAseq = VU.fromList . go where
-  go (VU.length -> 0) = []
-  go (VU.splitAt 3 -> (hs,ts)) = case M.lookup hs dnaAAmap of
-    Just aa -> aa : go ts
-    _       -> error $ "dnaAAseq: " ++ show (hs,ts)
-
--- | Transform an amino acid sequence back into DNA.
---
--- WARNING: This is lossy!
-
-aaDNAseq :: Primary AA -> Primary DNA
-aaDNAseq = VU.concatMap go where
-  go aa = case M.lookup aa aaDNAmap of
-            Just codon -> codon
-            Nothing    -> error $ "aaDNAseq" ++ show aa
-
-
--- * Embedded codon data
-
--- | Lossy backtransformation.
-
-aaDNAmap :: M.Map (Letter AA) (Primary DNA)
-aaDNAmap = M.fromList . map swap . M.assocs $ dnaAAmap
-{-# NOINLINE aaDNAmap #-}
-
-dnaAAmap :: Map (Primary DNA) (Letter AA)
-dnaAAmap = M.fromList . map (primary *** charAA) . M.assocs $ codonTable where
-{-# NOINLINE dnaAAmap #-}
-
-codonTable :: Map String Char
-codonTable = M.fromList . map (go . words) . lines . unpack $ codonListEmbedded where
-  go [cs,[c]] = (cs,c)
-  go e        = error $ "codonTable:" ++ show e
-{-# NOINLINE codonTable #-}
-
--- | Raw codon table
-
-codonListEmbedded :: ByteString
-codonListEmbedded = $(embedFile "sources/codontable")
--}
+  translateAllFrames tbl xs = VU.unfoldrN (VU.length xs) go 0
+    where go 0 = Just (Undef,1)
+          go 1 = Just (Undef,2)
+          go k = Just (translate tbl $ Codon (xs VU.! (k-2)) (xs VU.! (k-1)) (xs VU.! k), k+1)
+  {-# Inlinable translateAllFrames #-}
 
diff --git a/Biobase/Secondary/Diagrams.hs b/Biobase/Secondary/Diagrams.hs
--- a/Biobase/Secondary/Diagrams.hs
+++ b/Biobase/Secondary/Diagrams.hs
@@ -186,13 +186,13 @@
 -- TODO Check size of hairpins and interior loops?
 
 isCanonicalStructure :: String -> Bool
-isCanonicalStructure = all (`elem` "().")
+isCanonicalStructure = all (flip (elem @[]) "().")
 
 -- | Is constraint type structure, i.e. there can also be symbols present
 -- that denote up- or downstream pairing.
 
 isConstraintStructure :: String -> Bool
-isConstraintStructure = all (`elem` "().<>{}|")
+isConstraintStructure = all (flip (elem @[]) "().<>{}|")
 
 -- | Take a structural string and split it into its constituents.
 --
@@ -253,11 +253,11 @@
     g k st ('.':xs) = g (k+1) st xs
     g k st (x:xs) | l==x = g (k+1) (k:st) xs
     g k (s:st) (x:xs) | r==x = ((s,k):) <$> g (k+1) st xs
-    g k [] xs = fail $ printf "too many closing brackets at position %d: '%s' (dot-bracket: %s)" k xs str
-    g k st [] = fail $ printf "too many opening brackets, opening bracket(s) at: %s (dot-bracket: %s)" (show $ reverse st) str
-    g a b c   = fail $ printf "unspecified error: %s (dot-bracket: %s)" (show (a,b,c)) str
-  f xs lr@(_:_:_:_) = fail $ printf "unsound dictionary: %s (dot-bracket: %s)" lr str
-  f xs lr     = fail $ printf "unspecified error: dict: %s, input: %s (dot-bracket: %s)" lr xs str
+    g k [] xs = Left $ printf "too many closing brackets at position %d: '%s' (dot-bracket: %s)" k xs str
+    g k st [] = Left $ printf "too many opening brackets, opening bracket(s) at: %s (dot-bracket: %s)" (show $ reverse st) str
+    g a b c   = Left $ printf "unspecified error: %s (dot-bracket: %s)" (show (a,b,c)) str
+  f xs lr@(_:_:_:_) = Left $ printf "unsound dictionary: %s (dot-bracket: %s)" lr str
+  f xs lr     = Left $ printf "unspecified error: dict: %s, input: %s (dot-bracket: %s)" lr xs str
 
 -- | Calculates the distance between two vienna strings.
 
diff --git a/Biobase/Secondary/Isostericity.hs b/Biobase/Secondary/Isostericity.hs
--- a/Biobase/Secondary/Isostericity.hs
+++ b/Biobase/Secondary/Isostericity.hs
@@ -13,7 +13,7 @@
 module Biobase.Secondary.Isostericity where
 
 import           Data.ByteString.Char8 (ByteString)
-import           Data.FileEmbed (embedFile)
+import           Data.FileEmbed (makeRelativeToProject, embedFile)
 import           Data.Function (on)
 import           Data.List
 import           Data.Tuple.Select
@@ -86,11 +86,14 @@
             ) $ map entry xs where
     bpt = head $ head g
     xs = tail g
-    entry x = (x!!0, map (filter (\z -> not $ z `elem` "()")) . takeWhile ('I' `elem`) . drop 2 $ x)
+    entry x = (x!!0, map (filter (\z -> not $ z `elem` bracket)) . takeWhile ('I' `elem`) . drop 2 $ x)
+  bracket :: String
+  bracket = "()"
   turn entry@(((x,y),(wc,tx,ty)), cs) = [entry, (((y,x),(wc,ty,tx)), cs)]
 
 -- | Simple parsing of raw CSV data.
 
+parsedCSV :: [[[Field]]]
 parsedCSV = filter (not . null) gs where
   gs = map (filter ((""/=).head)) . groupBy (\x y -> ""/= (head y)) $ csv
   Right csv = parseCSV "isostericity/detailed" $ BS.unpack detailedCSV
@@ -102,5 +105,5 @@
 -- | Raw CSV data, embedded into the library.
 
 detailedCSV :: ByteString
-detailedCSV = $(embedFile "sources/isostericity-detailed.csv")
+detailedCSV = $(makeRelativeToProject "sources/isostericity-detailed.csv" >>= embedFile)
 
diff --git a/Biobase/Secondary/New.hs b/Biobase/Secondary/New.hs
--- a/Biobase/Secondary/New.hs
+++ b/Biobase/Secondary/New.hs
@@ -24,9 +24,9 @@
 -- TODO Should be extended with @Extended@, but this requires knowing which of
 -- the ends overlap with paired: left, right, or both.
 
-data SubStructure (t ∷ k) a
-  = Unpaired { _label ∷ !a }
-  | Paired   { _label ∷ !a, _subStructures ∷ !(Vector (SubStructure t a)) }
+data SubStructure (t :: *) a
+  = Unpaired { _label :: !a }
+  | Paired   { _label :: !a, _subStructures :: !(Vector (SubStructure t a)) }
   deriving (Show, Read, Functor, Traversable, Foldable, Generic, Eq, Ord)
 makeLenses ''SubStructure
 makePrisms ''SubStructure
@@ -34,8 +34,8 @@
 -- | A full structure is composed of a number of sub-structures. The empty
 -- structure is a full structure.
 
-newtype FullStructure (t ∷ k) a
-  = FullStructure { _fullStructure ∷ Vector (SubStructure t a) }
+newtype FullStructure (t :: *) a
+  = FullStructure { _fullStructure :: Vector (SubStructure t a) }
   deriving (Show, Read, Functor, Traversable, Foldable, Generic, Eq, Ord)
 makeLenses ''FullStructure
 
@@ -43,26 +43,26 @@
 
 -- ** Parses a ViennaRNA secondary structure string.
 
-pUnpaired ∷ Parser (SubStructure () ())
+pUnpaired :: Parser (SubStructure () ())
 pUnpaired = Unpaired () <$ char '.'
 {-# Inlinable pUnpaired #-}
 
-pPaired ∷ Parser (SubStructure () ())
+pPaired :: Parser (SubStructure () ())
 pPaired = Paired () <$ char '(' <*> (fromList <$> many pSubStructure) <* char ')'
 {-# Inlinable pPaired #-}
 
-pSubStructure ∷ Parser (SubStructure () ())
+pSubStructure :: Parser (SubStructure () ())
 pSubStructure = pUnpaired <|> pPaired
 {-# Inlinable pSubStructure #-}
 
-pFullStructure ∷ Parser (FullStructure () ())
+pFullStructure :: Parser (FullStructure () ())
 pFullStructure = FullStructure <$> fromList <$> many pSubStructure <* endOfInput
 {-# Inlinable pFullStructure #-}
 
 newtype StructureParseError = StructureParseError String
   deriving (Show)
 
-parseVienna ∷ MonadError StructureParseError m ⇒ ByteString → m (FullStructure () ())
+parseVienna :: MonadError StructureParseError m ⇒ ByteString -> m (FullStructure () ())
 parseVienna = either (throwError . StructureParseError) return . parseOnly pFullStructure
 {-# Inlinable parseVienna #-}
 
@@ -83,19 +83,19 @@
 -- @
 
 toTree
-  ∷ (SubStructure t a → Maybe b)
+  :: (SubStructure t a -> Maybe b)
   -- ^ how to handle substructure elements? @Nothing@ means discard this
   -- substructure and all children.
-  → b
+  -> b
   -- ^ The root label
-  → FullStructure (t ∷ k) a
+  -> FullStructure (t :: *) a
   -- ^ The @FullStructure@ to transform into a @Tree@.
-  → Tree b
+  -> Tree b
 toTree f r (FullStructure ts) = Node r $ fmap go ts ^.. traverse . _Just
   where
     go u@Unpaired{} = (`Node` []) <$> f u
     go p@Paired{}   = case f p of
-      Nothing  → Nothing
-      Just lbl → Just $ Node lbl $ (fmap go $ p^.subStructures) ^.. traverse . _Just
+      Nothing  -> Nothing
+      Just lbl -> Just $ Node lbl $ (fmap go $ p^.subStructures) ^.. traverse . _Just
 {-# Inlinable toTree #-}
 
diff --git a/Biobase/Secondary/Vienna.hs b/Biobase/Secondary/Vienna.hs
--- a/Biobase/Secondary/Vienna.hs
+++ b/Biobase/Secondary/Vienna.hs
@@ -33,6 +33,11 @@
 newtype ViennaPair = ViennaPair { unViennaPair :: Int }
   deriving (Eq,Ord,Generic,Ix)
 
+derivingUnbox "ViennaPair"
+  [t| ViennaPair -> Int |]
+  [| unViennaPair |]
+  [| ViennaPair |]
+
 instance Binary    (ViennaPair)
 instance Serialize (ViennaPair)
 instance FromJSON  (ViennaPair)
@@ -175,7 +180,4 @@
 cguaP = [CG .. UA]
 cgnsP = [CG .. NS]
 pairToString = [(CG,"CG"),(GC,"GC"),(UA,"UA"),(AU,"AU"),(GU,"GU"),(UG,"UG"),(NS,"NS"),(NP,"NP")]
-
-derivingUnbox "ViennaPair"
-  [t| ViennaPair -> Int |] [| unViennaPair |] [| ViennaPair |]
 
diff --git a/BiobaseXNA.cabal b/BiobaseXNA.cabal
--- a/BiobaseXNA.cabal
+++ b/BiobaseXNA.cabal
@@ -1,18 +1,18 @@
 cabal-version:  2.2
 name:           BiobaseXNA
-version:        0.11.0.0
+version:        0.11.1.0
 author:         Christian Hoener zu Siederdissen
 maintainer:     choener@bioinf.uni-leipzig.de
 homepage:       https://github.com/choener/BiobaseXNA
 bug-reports:    https://github.com/choener/BiobaseXNA/issues
-copyright:      Christian Hoener zu Siederdissen, 2011 - 2019
+copyright:      Christian Hoener zu Siederdissen, 2011 - 2021
 category:       Bioinformatics
 synopsis:       Efficient RNA/DNA/Protein Primary/Secondary Structure
 license:        BSD-3-Clause
 license-file:   LICENSE
 build-type:     Simple
 stability:      experimental
-tested-with:    GHC == 8.4.4
+tested-with:    GHC == 8.8, GHC == 8.10, GHC == 9.0
 description:
                 This is a base library for bioinformatics with emphasis on RNA
                 and DNA primary structure as well as amino acid sequences.
@@ -74,8 +74,9 @@
                , bimaps                   == 0.1.0.*
                , BiobaseENA               == 0.0.0.*
                , BiobaseTypes             == 0.2.0.*
+               , DPutils                  == 0.1.0.*
                , ForestStructures         == 0.0.1.*
-               , PrimitiveArray           == 0.9.1.*
+               , PrimitiveArray           == 0.10.1.*
   default-extensions: BangPatterns
                     , DataKinds
                     , DeriveDataTypeable
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Build Status](https://travis-ci.org/choener/BiobaseXNA.svg?branch=master)](https://travis-ci.org/choener/BiobaseXNA)
+![github action: master](https://github.com/choener/BiobaseXNA/actions/workflows/action.yml/badge.svg)
 
 # BiobaseXNA
 
