使用Haskell sum类型进行递归列表 - 递归锚?
为了更好地理解Haskell,我想使用sum类型来构建一些递归列表结构。使用Haskell sum类型进行递归列表 - 递归锚?
这两种类型是不相关的,但在同一个文件:
所以我得到一个错误“‘空’的多次声明”。阅读this后,我知道'空'不是一个关键字(正如我在这个数据类型在课堂上呈现时所假定的那样)。
如果我想在我的程序中使用n这样的类型,我必须为空元素提出n个不同的名称,这看起来不正确。
是否有一个共同的表达式来确定列表的结尾? 或者我应该不使用这种'自制'类型?
假设您已被允许使用Empty
构造函数声明两个数据类型,就像您所做的那样。鉴于定义
x = Empty
什么是x
的类型?它可能是EList
或ETree
,但电脑无法知道你的意思。这就是为什么一般来说,你不能在给定文件中多次声明相同名称的原因。
一个简单的解决方案就是简单地使用不同的名称。在这里,我使用Nil
作为空白列表,Leaf
作为空白树。
data List = Cons Point List | Nil
data Tree = Node Int Tree Tree | Leaf
(旁白:它通常不申报的总和类型记录的字段是个好主意,因为这意味着提取将部分功能。)
另一种方法是把你的两个重叠的名字在不同的文件。
List.hs:
module List where
data List = Cons Point List | Empty
Tree.hs:
module Tree where
data Tree = Node Int Tree Tree | Empty
现在,如果导入这两个模块,指的是Empty
不允许的,因为再一次机器不知道哪一个你的意思。但是这一次,你可以使用合格的名字自行排序。
import List
import Tree
emptyList = List.Empty
emptyTree = Tree.Empty
这是一个正确的答案,但我不禁要指出,如果语言需要像这样的含糊定义的类型声明,那么计算机将能够处理'x = Empty'定义。 Haskell已经为数字文字做了这个。所以这是一种语言规定的规则,而不是一些自然规律。 –
@LuisCasillas我同意,事实上有些语言比Haskell更加灵活地处理不同类型的重叠名称; Haskell选择优先化类型推断。尽管如此,数字文字并不是完全相同的东西;它们是多态的,具有'Num n => n'类型,所以类型是使用Haskell的常规实例选择规则选择的。 –
你为什么不直接叫第一个'Empty' - 'Nil'和第二个'Leaf'?那么它会'感觉不错'。但最终你必须 - 做到这一点 - 否则'空'可以用来构建树或列表 - 也许一些LANGUAGE扩展可以帮助你 - 我想'AllowAmbiguousTypes',但我不知道。 – epsilonhalbe
另一个选择是 - 因为它们不相关 - 创建两个模块 - MyList和MyTree - 然后,因为命名空间是每个模块,问题就解决了,如果您在一个文件中同时使用了两个模块,则必须执行限定的导入。看一看['containers'](https://hackage.haskell.org/package/containers)包,看看整齐排列的示例。 – epsilonhalbe