我正在尝试使用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&的新手。我无法弄清楚错误在哪里。 我哪里错了?
谢谢。
答案 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
为此,您需要修改数据结构