我有很多类型,它们的层次结构存储了一些有用的信息。我试图避免将类型层次结构的知识融入到对其进行操作的函数中。
以下是斯坦福自然语言处理的类型依赖的一小段摘录:
root - root
dep - dependent
aux - auxiliary
auxpass - passive auxiliary
cop - copula
arg - argument
agent - agent
我想创建一些反映此结构的数据类型,以便我可以定义一些只能对某些类型进行操作的函数。当我有一个运行在arg
,我用来表示的类型arg
还应包括agent
但类型为agent
不应包括arg
。类型为dep
应该包括其下面的任何内容。
这在 haskell 中可能吗?我一直在尝试声明各种data
类型来对此进行建模,但我无法让它工作,因为数据类型不能使用另一种数据类型的构造函数。
我怀疑这种方法可能不适用于 Haskell,所以如果是这种情况,您通常如何处理这些绝对不希望扁平化层次结构的情况?
一般来说,子类型与 Haskell 配合得不太好。但是,如果您只是尝试建模(非多重)继承(因此您有子类型树而不是晶格),则实际上可以使用类型类构建子类型。这是一个简短的要点,正是这样做的。从那里开始,您定义数据类型
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
围绕超级类型和embedImmediate = coerce
(from Data.Coerce
)
那么,你不能quite只需在需要超类型的函数中使用子类型,但几乎:您只需添加对embed
(不同于embedImmediate
!)从子类型转换为所需的任何超类型(基于类型推断)。您可能想查看一些示例使用.
请注意,您现在可以使用<:
作为约束:某物的类型是某物的子类型Aux
,例如,是(a <: Aux) => a
。每当你想要这个东西被视为Aux
(或超类型Aux
), call embed
on it.
这种方法的一个很大的缺点是输入和输出类型必须被注释(否则不清楚which你想要的超类型embed
进入,你会得到“模糊类型”错误)。如果您已经写了很多签名,那么应该没问题。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)