在Haskell中使用递归数据类型创建后向列表

时间:2011-06-21 05:08:47

标签: haskell

我正在尝试使用Haskell的递归类型

创建一个后向列表
data RevList a = Snoc a (RevList a) | Lin
    deriving Show 

mkrevlst [] = Lin
mkrevlst (x:xs) = mkrevlst xs Snoc x 

当我执行> mkrevlst [1,2,3]时,我期望的输出是:((Lin Snoc 3) Snoc 2) Snoc 1

当我运行时,我收到错误。我是Haskell&的新手。我无法弄清楚错误在哪里。 我哪里错了?

谢谢。

3 个答案:

答案 0 :(得分:3)

我不确定这条线应该是什么,但它没有意义:

mkrevlst (x:xs) = mkrevlst xs Snoc x 

表达式mkrevlist xs可能具有类型RevList a,因为上面的基本情况返回Lin。将此应用于另外两个参数确实会导致类型错误。

看起来就像你期望Snoc使用中缀一样,这是正确的吗?在Haskell中,由字母数字字符组成的标识符是前缀,除非被反引号包围,例如mkrevlist xs `Snoc` x。由符号组成的标识符是中缀,除非括在括号中,并且中缀数据构造函数必须以冒号开头。所以你也可以像这样定义你的数据类型:

data RevList a = a :| (RevList a) | Lin
    deriving Show 

另请注意,即使您使用Snoc infix,其参数的顺序仍然与您在mkrevlist中使用它的方式相反。

答案 1 :(得分:3)

事物列表要么是空的,要么后面是事物列表。这正是您对RevList的定义所具有的。它与普通列表同构,完全没有反转。真正的反向列表是与普通列表对称定义的。

  

事物列表是空的或者是   之后是一系列事情。

对称地,

  

反向清单是空的或者是   反向列出的东西后跟一个   的事情。

在Haskell中重写一下,使用中缀数据构造函数,就像在camccann的答案中一样,你会得到你期望的结果。

答案 2 :(得分:0)

试试这个:

mkrevlst [] = Lin
mkrevlst (x:xs) = Snoc x (mkrevlst xs)

Snoc构造函数需要2个参数,因为你只传递了一个,即x 它将解决错误,但它不会解决您创建输出的问题,如:

((Lin Snoc 3) Snoc 2) Snoc 1

为此,您需要修改数据结构