Loops Haskell堆栈实现
这是我第一次在StackOverflow上发帖。我正在学习Haskell,并试图制作一个操作堆栈的函数Loops Haskell堆栈实现,loops,haskell,stack,Loops,Haskell,Stack,这是我第一次在StackOverflow上发帖。我正在学习Haskell,并试图制作一个操作堆栈的函数test。它将整数列表作为输入,然后执行以下操作: 如果数字为偶数: 如果数字是24,并且在当前索引之前的输入列表中没有出现2,那么我们抛出一个错误 否则,我们将数字推送到堆栈中 例如,list=[0,1,2,3,4,24]。列表中出现了2,因此我们将24推到堆栈中 如果数字为奇数: 如果堆栈顶部==当前数字-1,则从堆栈中弹出。否则,我们抛出一个错误 如果弹出堆栈后堆栈为空,我们将显示
test
。它将整数列表作为输入,然后执行以下操作:
- 如果数字是24,并且在当前索引之前的输入列表中没有出现2,那么我们抛出一个错误
- 否则,我们将数字推送到堆栈中
- 例如,
。列表中出现了2,因此我们将24推到堆栈中list=[0,1,2,3,4,24]
- 如果堆栈顶部==当前数字-1,则从堆栈中弹出。否则,我们抛出一个错误
- 如果弹出堆栈后堆栈为空,我们将显示一条“成功”消息
push
、pop
、peek
操作具有O(1)
复杂性,但我相信一定有更好的实现方法:
emptyStack :: [a]
emptyStack = []
push :: a -> [a] -> [a]
push item xs = item : xs
pop :: [a] -> [a]
pop [] = error "Cannot pop from empty stack."
pop xs = tail xs
peek :: [a] -> a
peek = head
对于test
函数,这就是我提出的这个怪物,它不会在列表中迭代,而且stack=emptyStack
没有意义:
test :: Integral a => [a] -> Either String [a]
test [] = Left "Empty input list"
test (x:xs) | even x = if x == 24 && notElem 2 (x:xs) then Left "Error!"
else Right (push x stack)
| odd x = if null (Right (pop xs)) then Left "Success~" else
(if peek stack == x - 1 then Right (pop stack)
else Left "Not 1 less than current number!")
where stack = emptyStack
我的
测试
实现应该如何修改以满足开头提到的要求?提前谢谢 另一种可能的方法是:不要硬连接堆栈。使函数同时接受堆栈和指令列表,并返回修改后的堆栈和修改后的指令列表(或错误)。小心不要将堆栈与指令列表混淆,因为它们的类型完全相同。也许您可以先专注于执行一个步骤,然后将您的解决方案扩展到使用整个指令列表的解决方案代码有问题:上的null
对于左
值,其中一个
始终为真
,对于右
值,始终为假
。(为什么null
与或一起工作?
这是一个很长的故事,它涉及到一种叫做可折叠的)您总是将null与右值一起使用。也许你的意思不同,比如直接检查popxs
是否为空?通常,对列表执行模式匹配(case pop xs of[]->..z:zs->..
)是检测列表是否为空的更好方法。@danidiaz感谢您的回复!关于您的第一条注释,我的意思是函数应该在从堆栈中弹出一个元素后立即检查堆栈是否为空,因此我使用了Right(popxs)
。关于第二条评论,你能告诉我你所说的“说明清单”是什么意思吗?这是指开始时的需求,还是指整数的输入列表?是的,我指的是整数列表。我仍然不明白为什么要使用Right(popxs)
。您正在计算popxs
,将其包装在右侧
,并对其调用null
。为什么要添加右侧的
?您可以在ghci中尝试键入类似于null(右([]::[Int])
或null(右[1::Int,2])
的内容。您将看到它总是返回False
@danidiaz我试图匹配函数的类型签名,因此我加入了Right
来匹配字符串[Int]
。但是现在我明白你的观点了,事实上没有理由在那里添加右边的。