gpt4 book ai didi

haskell - 构建更高级的通用解析器

转载 作者:行者123 更新时间:2023-12-02 18:28:12 34 4
gpt4 key购买 nike

好的,这是我之前问题的延续 (Generically) Build Parsers from custom data types? 。我接受了建议并决定使用 generic-sop 构建我的解析器,到目前为止一切都很顺利。

我需要稍微扩展我的实现,以便可以处理更复杂的情况。也就是说,考虑这两个 data 定义,其中 B 构建在 A 之上:

data A = A String Int

data B = B A Double

为了通用地解析所有数据结构,我定义了以下:

class HasSimpleParser f where
getSimpleParser :: Parser f

class Parsable f where
getParser :: Parser f

class GenericallyParsable f where
getGenericParser :: Parser f

Int、String、Double等基本类型可以轻松地制作成HasSimpleParser的实例。然后我通过执行以下操作将 A 等数据结构作为 Parsable 的实例

instance (Generic r, Code r ~ '[xs], All HasSimpleParser xs) => Parsable r where
getParser = to . SOP. Z <$> hsequence (hcpure (Proxy @HasSimpleParser) getSimpleParser)

我引入了类GenericParsable来解析像B这样的数据结构。所以我执行以下操作:

 instance (Generic r, Code r ~ '[xs], All Parsable xs) => GenericallyParsable r where
getGenericParser = to . SOP. Z <$> hsequence (hcpure (Proxy @Parsable) getParser)

最后一 block 拼图是解析函数:

parseA :: InputStream ByteString -> IO A
parseA = parseFromStream (getGenericParser @A)

parseB :: InputStream ByteString -> IO B
parseB = parseFromStream (getGenericParser @B)

但是,代码无法编译,并且出现以下错误:

• 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)

那么我应该如何修改代码才能工作呢?

最佳答案

我认为 GenericParsable 类型类不是必需的。

只需为A定义一个HasSimpleParser实例,它搭载在Parsable上:

instance HasSimpleParser A where
getSimpleParser = getParser

如果您最终为记录声明了许多这种类型的实例,您可以使用 {-# language DefaultSignatures #-} 对其进行一些简化。并将 HasSimpleParser 的定义更改为

class HasSimpleParser c where
getSimpleParser :: Parser c
default getSimpleParser :: Parsable c => Parser c
getSimpleParser = getParser

现在在记录实例中您只需编写:

instance HasSimpleParser A
<小时/>

事实上,HasSimpleParserParsable 之间的区别也许是不必要的。一个包含基本类型和复合类型实例的 HasParser 类型类就足够了。默认实现将使用 generics-sop 并需要 (Generic r, Code r ~ '[xs], All HasParser xs) 约束。

class HasParser c where
getParser :: Parser c
default getParser :: (Generic c, Code c ~ '[xs], All HasParser xs) => Parser c
getParser = ...generics-sop code here...

关于haskell - 构建更高级的通用解析器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43855273/

34 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com