我有一堆类型,它们的层次结构存储了一些有用的信息。我试图避免将类型层次结构的知识融入到对它们进行操作的函数中。
以下是斯坦福自然语言处理的 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 = ...
如何填写
...
你决定。您可以为此做几件事:embedImmediate
返回该字段 data
定义看起来更整洁,但您的 embedImmediate
定义会长一点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/