haskell - 如何在 Haskell 中对分层数据类型进行建模?

标签 haskell

我有一堆类型,它们的层次结构存储了一些有用的信息。我试图避免将类型层次结构的知识融入到对它们进行操作的函数中。

以下是斯坦福自然语言处理的 Typed Dependencies 的一小部分摘录:

root - root
dep - dependent
  aux - auxiliary
    auxpass - passive auxiliary 
    cop - copula
  arg - argument 
    agent - agent

我想创建一些反射(reflect)这种结构的数据类型,以便我可以定义一些只能对某些类型进行操作的函数。当我有一个在 arg 上运行的函数时,我用来表示的类型arg还应包括 agent但是 agent 的类型不应包含 arg . dep 的类型应该包括它下面的任何东西。

这在haskell中可能吗?我一直在尝试声明各种data类型来对此进行建模,但我无法让它工作,因为数据类型不能使用另一种数据类型的构造函数。

我怀疑这种方法可能不适用于 Haskell,所以如果是这种情况,您通常如何处理这些绝对不希望扁平化层次结构的情况?

最佳答案

一般来说,子类型在 Haskell 中表现不佳。但是,如果您只是尝试对(非多重)继承进行建模(因此您有一个子类型树而不是一个格子),您实际上可以使用类型类构建子类型。 Here is a short gist that does exactly this.从那里开始,您定义数据类型

data Root = Root ...
data Dep = Dependent ...
data Aux = Auxiliary ...
data AuxPass = PassiveAuxiliary ... 
data Cop = Copula ...
data Arg = Argument ...
data Agent = Agent ...

以及对应的实例
instance Subtype Aux where
  type SuperType Aux = Dep
  embedImmediate = ...

instance Subtype AuxPass where
  type SuperType AuxPass = Aux
  embedImmediate = ...

instance Subtype Cop where
  type SuperType Cop = Aux
  embedImmediate = ...

instance Subtype Arg where
  type SuperType Arg = Dep
  embedImmediate = ...

instance Subtype Agent where
  type SuperType Agent = Arg
  embedImmediate = ...

如何填写...你决定。您可以为此做几件事:
  • 如果您的子类型在父类(super class)型之上添加了许多字段,则始终如一地添加一个具有父类(super class)型的字段并制作 embedImmediate返回该字段
  • 如果您的子类型仅添加几个字段,您可能需要手动解压缩它们。您的 data定义看起来更整洁,但您的 embedImmediate定义会长一点
  • 如果您的子类型没有向父类(super class)型添加任何字段,您可以创建一个 newtype围绕父类(super class)型和embedImmediate = coerce (来自 Data.Coerce )

  • 然后,您不能只在需要父类(super class)型的函数中使用子类型,而是几乎:您只需添加对 embed 的调用即可。 (不同于 embedImmediate !)从子类型转换为所需的任何父类(super class)型(基于类型推断)。您可能想查看 some example uses .

    请注意,您现在可以使用 <:作为约束:作为 Aux 子类型的某物的类型,例如,是 (a <: Aux) => a .每当您希望将此事物视为 Aux (或 Aux 的 super 类型),请调用 embed在上面。

    这种方法的一大缺点是必须对输入和输出类型进行注释(否则不清楚你想要embed 进入哪个父类(super class)型,你会得到“模糊类型”错误)。如果你已经写了很多签名,你应该没问题。

    关于haskell - 如何在 Haskell 中对分层数据类型进行建模?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41504364/

    相关文章:

    python - 我们怎么称呼这个(新的?)高阶函数?

    haskell - "Pattern match"并递归封闭类型族中的类型以进行类型相等证明

    haskell神奇的代码,这里发生了什么

    haskell - 在 Netwire 中切换

    haskell - 在 JavaScript 中嵌入 Heist 标签

    haskell - 为什么我的函数不适用于无限列表?

    performance - STM 性能不佳/锁定

    haskell - 约束封闭型族

    haskell - 为什么 `do` block 中的类型在下一行匹配,但在同一行不匹配?

    haskell - 将自定义数据类型编码为惰性字节字符串