ok, here is a continuation of my previous question (Generically) Build Parsers from custom data types?. I took the advice and decided to build my parsers with generic-sop and all was going fine until now.
I need to expand my implementation a little bit so more complicated situations can be dealt with. Namely, consider these two data
definitions, where B
is built on top of A
:
data A = A String Int
data B = B A Double
In order to generically parse all data
structures, I define the following class
:
class HasSimpleParser f where
getSimpleParser :: Parser f
class Parsable f where
getParser :: Parser f
class GenericallyParsable f where
getGenericParser :: Parser f
The primitive types such as Int, String, Double
etc can be made into instances of HasSimpleParser
easily. Then I make data structure such as A
an instance of Parsable
by doing
instance (Generic r, Code r ~ '[xs], All HasSimpleParser xs) => Parsable r where
getParser = to . SOP. Z <$> hsequence (hcpure (Proxy @HasSimpleParser) getSimpleParser)
I introduce the class GenericallyParsable
to parse data structure like B
. So I do the following:
instance (Generic r, Code r ~ '[xs], All Parsable xs) => GenericallyParsable r where
getGenericParser = to . SOP. Z <$> hsequence (hcpure (Proxy @Parsable) getParser)
The last pieces of the puzzle are the parsing functions:
parseA :: InputStream ByteString -> IO A
parseA = parseFromStream (getGenericParser @A)
parseB :: InputStream ByteString -> IO B
parseB = parseFromStream (getGenericParser @B)
However, the code won't compile and I got the following error:
• Couldn't match type ‘'['[Char, [Char]]]’ with ‘'[]’
arising from a use of ‘getGenericParser’
• In the first argument of ‘parseFromStream’, namely
‘(getGenericParser @A)’
In the expression: parseFromStream (getGenericParser @A)
In an equation for ‘parseA’:
parseA = parseFromStream (getGenericParser @A)
So how should I modify the code to work?