Writing Read instances for HList I'm a total newbie at parsing, so I figured I'd start by writing instances of Read for HList, which does not currently have them. I'd appreciate some feedback on the following:

{-# LANGUAGE
  DataKinds
 ,KindSignatures
 ,FlexibleContexts
 ,FlexibleInstances
 ,TypeOperators
 ,GADTs
 ,ScopedTypeVariables
 #-}

module MyHList where
import GHC.Read
import Text.ParserCombinators.ReadPrec
import qualified Text.Read.Lex as L

-- This declaration is copied from `Data.HList.HList`.
data HList (l::[*]) where
  HNil  :: HList '[]
  HCons :: e -&gt; HList l -&gt; HList (e ': l)

infixr 2 `HCons`


instance Read (HList '[]) where
  readPrec = parens
    ( do
        expectP (L.Ident "H")
        expectP (L.Punc "[")
        expectP (L.Punc "]")
        return HNil
    )

instance forall e . Read e =&gt; Read (HList (e ': '[])) where
  readPrec = parens
    ( do
        expectP (L.Ident "H")
        expectP (L.Punc "[")
        e &lt;- reset $ (readPrec::ReadPrec e)
        expectP (L.Punc "]")
        return (e `HCons` HNil)
    )

instance forall e f (l::[*]) . (Read e, ReadTl (HList (f ': l))) =&gt;
   Read (HList (e ': f ': l)) where
  readPrec = parens
    ( do
        expectP (L.Ident "H")
        expectP (L.Punc "[")
        e &lt;- reset $ (readPrec::ReadPrec e)
        expectP (L.Punc ",")
        rest &lt;- readTl :: ReadPrec (HList (f ': l))
        return (e `HCons` rest)
    )

class ReadTl l where
  readTl :: ReadPrec l

instance forall e . Read e =&gt; ReadTl (HList (e ': '[])) where
  {-# INLINE readTl #-}
  readTl = do
    e &lt;- reset $ (readPrec::ReadPrec e)
    expectP (L.Punc "]")
    return $ e `HCons` HNil

instance forall e f (l::[*]) . (Read e, ReadTl (HList (f ': l)))
             =&gt; ReadTl (HList (e ': f ': l)) where
  {-# INLINE readTl #-}
  readTl = do
    e &lt;- reset $ (readPrec::ReadPrec e)
    expectP (L.Punc ",")
    rest &lt;- readTl
    return (e `HCons` rest)
This is indeed interesting challenge!

-- Read after H[
class ReadHList (a :: [*]) where
  readHList :: ReadPrec (HList a)

-- Read after element:
-- ] for nil
-- , readHList for cons 
class ReadHListAfter (a :: [*]) where
  readHListAfter :: ReadPrec (HList a)

instance ReadHList '[] where
  readHList = expectP (L.Punc "]") &gt;&gt; return HNil

instance ReadHListAfter '[] where
  readHListAfter = readHList

instance (Read a, ReadHListAfter l) =&gt; ReadHList (a ': l) where
  readHList = ...

-- We could use ReadHList (a ': l) as additional constraint,
-- But then we need UndecidableInstances extension
instance (Read a, ReadHListAfter l) =&gt; ReadHListAfter (a ': l) where
  readHListAfter = ...

-- Parsing HList is trivial as composing functions!
instance ReadHList a =&gt; Read (HList a) where
  readPrec = parens $ do
    expectP (L.Ident "H")
    expectP (L.Punc "[")
    readHList


This way it's a bit more elegant. IMHO.

Compare it to pseudo-codish parsing of lists of known length (aka vectors):

list :: Int -&gt; Parser a -&gt; Parser [a]
list n p =
  token '['
  list' n p

list' :: Int -&gt; Parser a -&gt; Parser [a]
list' 0 _ = token ']' &gt;&gt; return []
list' n p = do
  h &lt;- p
  t &lt;- listTail (n - 1) p
  return (h : t)

listTail :: Int -&gt; Parser a -&gt; Parser [a]
listTail 0 _ = token ']' &gt;&gt; return []
listTail n = do
  h &lt;- p
  token ','
  t &lt;- listTail (n - 1) p
  return (h : t)