List 哈斯克尔:RPN计算器

List 哈斯克尔:RPN计算器,list,haskell,console,List,Haskell,Console,我想开发一种堆栈管理系统。列表以空[]开始,用户可以输入数字,这些数字将被添加到列表中,以及二进制操作,二进制操作将从列表中取出前两个数字并执行该操作,然后将其放回列表中。例如: [] : 3 [3] : 4 [4,3] : + [7] : c [] : 123 [123] : 3 [3,123] : * [369] : 我不知道如何从控制台处理输入。我有一个坏代码: import System.Environment import System.Directory import S

我想开发一种堆栈管理系统。列表以空[]开始,用户可以输入数字,这些数字将被添加到列表中,以及二进制操作,二进制操作将从列表中取出前两个数字并执行该操作,然后将其放回列表中。例如:

[] : 3
[3] : 4
[4,3] : +
[7] : c
[] : 123
[123] : 3
[3,123] : *
[369] :
我不知道如何从控制台处理输入。我有一个坏代码:

import System.Environment   
import System.Directory  
import System.IO  
import Data.List  

stack = []

add1 :: [Int] -> [Int]
add1 [] = []
add1 [x] = [x]
add1 [x,y] = [(x+y)]
add1 x:(y:xs) = (x+y) : (xs : []) 

--sub :: [Int] -> [Int]
--sub [] = []
--sub x:(y:xs) = (x-y) : xs 

--mul :: [Int] -> [Int]
--mul [] = []
--mul x:(y:xs) = (x*y) : xs 

--div :: [Int] -> [Int]
--div [] = []
--div x:(y:xs) = (x/y) : xs 

c :: [Int] -> [Int]
c = []

push :: [Int] -> a -> [Int]
push [] a = [a]
push (x:xs) a = a : (x:xs)

dispatch :: [(String, Int -> IO ())]
dispatch =  [ ("+", add)
       --     , ("-", sub)
       --     , ("*", mul)
       --     , ("/", div)
            ]

xcl = do
    print stack
    answer <- readLine
但我甚至不知道我的方向是否正确。任何帮助都会很好。多谢各位

xcl stack = do
    print stack
    answer <- getLine
    case lookup answer dispatch of
        Just function -> -- we have a function, apply it to the top of the stack
        Nothing -> -- if we have a number, parse it and push it onto the stack
                   -- if not, issue an error
堆栈不能是顶级常量,因为我们需要操纵它。所以我们把它作为xcl的一个参数。 使用getLine读取一行文本,因为我们不知道是要将其解释为运算符名称还是数字。 堆栈不能是顶级常量,因为我们需要操纵它。所以我们把它作为xcl的一个参数。 使用getLine读取一行文本,因为我们不知道是要将其解释为运算符名称还是数字。 你在正确的道路上;让我们看看我建议对代码的一些更改

您的add1函数非常接近,但是您有两个小问题-第一个是您提供的模式匹配:为了语法正确,您需要将整个匹配放在括号内。第二个是第二个冒号。cons的类型为a->[a]->[a],因此它可以完美地使用x+y作为第一个参数;但是,由于xs已经有[Int]类型,所以不需要提供:[]

接下来,因为您要处理的是整型和整型列表,所以在此上下文中使用某种类型a是没有意义的

push :: [Int] -> Int -> [Int]
最后,您的主力军功能。由于Haskell中缺少循环构造,因此执行用户输入循环的方法也是通过递归实现的。因此,接受一个参数是有意义的。让我们把它作为[Int]堆栈。将stdin中的一行作为字符串读取的函数是getLine,它的类型为IO string。最后,您实际上必须处理该输入。为简单起见,我刚刚在xcl中的case语句中包含了该逻辑,但它也可以使用dispatch或类似的函数来完成。事实上,如果您的RPN计算器变得更复杂,这将有其优点。每种情况下的操作都应该使用修改后的堆栈递归到xcl循环中。当你退出时,它应该退出——这是return的一个很好的用法

你在正确的道路上;让我们看看我建议对代码的一些更改

您的add1函数非常接近,但是您有两个小问题-第一个是您提供的模式匹配:为了语法正确,您需要将整个匹配放在括号内。第二个是第二个冒号。cons的类型为a->[a]->[a],因此它可以完美地使用x+y作为第一个参数;但是,由于xs已经有[Int]类型,所以不需要提供:[]

接下来,因为您要处理的是整型和整型列表,所以在此上下文中使用某种类型a是没有意义的

push :: [Int] -> Int -> [Int]
最后,您的主力军功能。由于Haskell中缺少循环构造,因此执行用户输入循环的方法也是通过递归实现的。因此,接受一个参数是有意义的。让我们把它作为[Int]堆栈。将stdin中的一行作为字符串读取的函数是getLine,它的类型为IO string。最后,您实际上必须处理该输入。为简单起见,我刚刚在xcl中的case语句中包含了该逻辑,但它也可以使用dispatch或类似的函数来完成。事实上,如果您的RPN计算器变得更复杂,这将有其优点。每种情况下的操作都应该使用修改后的堆栈递归到xcl循环中。当你退出时,它应该退出——这是return的一个很好的用法

读这个。这可能会有帮助。

请阅读此内容。这可能会有帮助

xcl :: [Int] -> IO ()
xcl st = do
    print st
    answer <- getLine
    case answer of
      "q" -> return ()
      "c" -> xcl ([] ::[Int])
      "+" -> xcl $ add1 st
      x -> xcl $ push st $ read x
      x -> case (reads x) of
        [(num,_)] -> xcl $ push st num
        _ -> xcl st