问题
I am trying to create a backward list using Haskell's recursive types
data RevList a = Snoc a (RevList a) | Lin
deriving Show
mkrevlst [] = Lin
mkrevlst (x:xs) = mkrevlst xs Snoc x
When I do > mkrevlst [1,2,3]
,the output I am expecting is : ((Lin Snoc 3) Snoc 2) Snoc 1
When I run this I get an error. I am new to Haskell & I am not able to make out where is mistake is. Where am I going wrong?
Thank you.
回答1:
I'm not sure what this line was supposed to be, but it doesn't make sense as is:
mkrevlst (x:xs) = mkrevlst xs Snoc x
The expression mkrevlist xs
presumably has type RevList a
, since the base case above returns Lin
. Applying this to two more arguments will indeed result in a type error.
It looks like you're expecting Snoc
to be used infix, is that correct? In Haskell, identifiers made of alphanumeric characters are prefix, unless surrounded by backticks, e.g. mkrevlist xs `Snoc` x
. Identifiers made of symbols are infix, unless surrounded in parentheses, and infix data constructors specifically must start with a colon. So you could also define your data type like this:
data RevList a = a :| (RevList a) | Lin
deriving Show
Also, note that even if you do use Snoc
infix, the order of its arguments are still backwards from how you're using it in mkrevlist
.
回答2:
A list of things is either empty or a thing followed by a list of things. This is exactly what you have as your definition of RevList. It is isomorphic to a normal list, not reversed at all. A real reversed list is defined symmetrically to a normal list.
A list of thing is either empty or a thing followed by a list of things.
Symmetrically,
A reversed-list of things is either empty or a reversed-list of things followed by a thing.
Rewrite this in Haskell, using an infix data constructor as in camccann's answer, and you will get what you expect.
回答3:
Try out this:
mkrevlst [] = Lin
mkrevlst (x:xs) = Snoc x (mkrevlst xs)
Snoc constructor need 2 parameters where as you were passing only one i.e x It will solve the error but it wont solve your problem of creating a output like:
((Lin Snoc 3) Snoc 2) Snoc 1
For this you need to modify your data structure
来源:https://stackoverflow.com/questions/6420606/creating-a-backward-list-using-recursive-data-type-in-haskell