如何在 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 的解析器,因为它们都是相同的类型。
我正在尝试将 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 适合该文件的记录列表的函数(我根据文件名来决定)。我运行进入“刚性类型变量”错误(类似于
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 的解析器,因为它们都是相同的类型。