How to use GHC’s `ReadPrec`?

72 views Asked by At

The documentation for GHC.Read describes readPrec only by:

Proposed replacement for readsPrec using new-style parsers (GHC only).

Other functions, types, etc. have no documentation at all. How do I use the supposedly more efficient parsing functionality in the intended way? Why is it more efficient?


The toy example I’d like to try out the new GHC approach is this:

data RoseTree a = RoseTree a [RoseTree a] deriving (Eq)

-- | A RoseTree is being displayed "label[children…]" for
-- | nonempty children and just "label" for a leaf (= tree with no children).
instance Show a => Show (RoseTree a) where
    show (RoseTree label []) = show label
    show (RoseTree label ts) = show label ++ show ts

-- | Parses outputs of `show` to a RoseTree.
instance Read a => Read (RoseTree a) where
    readsPrec n str = do
        (label, labelRemaining) <- readsPrec n str
        let tsReads = readsPrec n labelRemaining
        (ts, tsRemaining) <- ([], labelRemaining) : tsReads
        return (RoseTree label ts, tsRemaining)

I wrote this several years back for my Bachelor’s thesis and to be honest, I don’t understand the Read instance anymore. The code includes the Show instance as Read morally requires Show and should be compatible with it.

1

There are 1 answers

0
Daniel Wagner On BEST ANSWER

ReadPrec is (slightly) further documented in Text.ParserCombinators.ReadPrec. It implements the usual parser classes (Applicative, Monad, Alternative), so you should be able to use it something like this:

instance Read a => Read (RoseTree a) where
    -- a instance              vvvvvvvv
    readPrec = liftA2 RoseTree readPrec (readPrec <|> pure [])
    -- [RoseTree a] instance             ^^^^^^^^
    readListPrec = readListPrecDefault

You may want to think how this should interact with precedence, then insert appropriate calls to step and prec. You might also choose to use <++ over <|>; the former is generally more efficient but may commit to its first argument too soon and prevent certain things from parsing that otherwise ought to.