代码之家  ›  专栏  ›  技术社区  ›  GTF

如何在Haskell中进行多态解析

  •  0
  • GTF  · 技术社区  · 3 年前

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

    data RecordTypeA = RecordTypeA { ... }
    data RecordTypeB = RecordTypeB { ... }
    
    instance MyItemClass RecordTypeA where
      ...
    instance MyItemClass RecordTypeB where
      ...
    
    -- and loads of instances for parsing, serialising, etc..
    

    在尝试这样做时,我遇到了两个问题:

    首先,我不能编写一个需要 FilePath 作为输入,并返回适用于该文件的记录列表(我根据文件名决定)。我遇到了“刚性类型变量”错误(类似于 Rigid type variable in Haskell ). 我想这是一种动态调度,但我不知道如何在haskell中实现它。

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

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

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

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

    0 回复  |  直到 3 年前
        1
  •  2
  •   amalloy    3 年前

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

    data SomeRecord = TypeA RecordTypeA | TypeB RecordTypeB ...
    

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