如何在 Haskell 中进行多态解析

How to parse polymorphically in Haskell

我正在尝试将 CSV 文件夹解析为不同特定类型的 class,然后将其编译为单个 XLSX。我有不同的数据类型来表示记录,因为虽然所有这些都属于同一类事物,但它们具有不同的字段和解析方法:

data RecordTypeA = RecordTypeA { ... }
data RecordTypeB = RecordTypeB { ... }

instance MyItemClass RecordTypeA where
  ...
instance MyItemClass RecordTypeB where
  ...

-- and loads of instances for parsing, serialising, etc..

我 运行 在尝试这样做时遇到两个问题:

首先,我无法编写一个将 FilePath 作为输入和 returns 适合该文件的记录列表的函数(我根据文件名来决定)。我运行进入“刚性类型变量”错误(类似于)。我想这是一种动态调度,但我不知道如何在 haskell.

中实现它
parseRecords :: FilePath -> ExceptT ProgrammeError IO [a]
parseRecords = {- parses based on the file name -}
-- uh oh: "... a is a rigid type variable ..."

其次,如果我有那个功能,我不完全确定我将如何表示这些多态类型的列表,因为它必须是一个异构列表,所有这些都受它们是某组类型classes。我事先不知道会有多少不同类型的文件。

processFiles :: FilePath -> ExceptT ProgrammeError IO (Compiled a)
processFiles = ???

如何在 Haskell 中实现这种多态解析?

最直接的做法是将其降低到值级别,而不是尝试在编译时在类型级别上执行所有操作。定义一个新类型,它是您希望能够在此上下文中解析的所有内容的总和:

data SomeRecord = TypeA RecordTypeA | TypeB RecordTypeB ...

然后你可以做任意数量的事情——例如,定义一个[Parser SomeRecord]类型的列表,并且运行每个解析器从列表上输入。或者根据文件名,选择不同的解析器列表。那么parseRecords的结果可以是[SomeRecord]。这不是最精确的类型:您将不得不应对返回 TypeA 记录的可能性,即使您提供的解析器列表不包括 TypeA 的解析器,因为它们都是相同的类型。