用Haskell构建一个计算器,它可以接受两个以上的参数



我正在尝试在哈斯克尔中制作一个计算器。我已经做到了可以接受两个参数的程度。但是我被困在一个可能需要两个以上论点的地步上。例如,输入类型为 (+1 2(,打印 3。但现在它应该能够接收 (+1 2 3( 并打印出 6。

代码在这里:

import System.IO
main = do loop []
leadingNonSpaces [] = 0
leadingNonSpaces (' ':cs) = 0
leadingNonSpaces (c:cs) = 1 + (leadingNonSpaces cs)
keepNonSpaces cs = take (leadingNonSpaces cs) cs
firstWord cs = keepNonSpaces cs
second x = head (drop 1 x)
-- evaluation loop, taking list of defined variables (var, value) tuples
-- reads a statement and prints out its value
loop vars = do
     eof <- isEOF
     if eof
     then return ()
     else do line <- getLine
             if ((firstWord line) == "set")
               then do
                 let tokens = (drop 1 (tokenize line))
                 let value = (eval vars (second tokens))
                 putStrLn (show value)
                 loop (((head tokens),value):vars)
               else do
                 let res = eval vars line
                 putStrLn (show res)
                 loop vars
-- split string into space-separated tokens, but counting
--   a parenthesized subexpression as a single token
tokenize [] = []
tokenize (' ':cs) = tokenize cs
tokenize cs = let i = charsInToken cs
  in (take i cs):(tokenize (drop i cs))
-- returns # characters in first token; counts parenthesized
-- expression as a single token
charsInToken str = helper str 0
  -- helper takes string and number of open parentheses to be matched
  -- returns number of chars in first token
  where helper [] 0 = 0
        helper (' ':cs) 0 = 0
        helper (' ':cs) d = 1 + (helper cs d)
        helper ('(':cs) d = 1 + (helper cs (d+1))
--        helper (')':cs) 1 = 1              -- correct, but unnecessary
        helper (')':cs) d = 1 + (helper cs (d-1))
        helper (c:cs) d = 1 + (helper cs d)
-- evaluates expression in its argument string, returning an int
-- first argument is list of (var, value) tuples for declared variables
eval vars ('(':cs) = eval vars (take ((length cs)-1) cs)
eval vars (c:cs) = if (elem c "0123456789")
              then read (c:cs) :: Int
              else let ts = tokenize (c:cs)
                in if (elem (head (head ts)) "+-*/")
                   then apply_op (head ts) (map (eval vars) (drop 1 ts))
                   else lookupVar vars (head ts)
-- look up a variable in the list of (variable, value) tuples and
-- return corresponding value
lookupVar [] v = error ("Undefined variable: " ++ v)
lookupVar ((var,val):ts) v = if(v == var)
                             then val
                             else lookupVar ts v
-- apply an operator to a list of two integers
apply_op "+" [arg1, arg2] = arg1 + arg2
apply_op "-" [arg1, arg2] = arg1 - arg2
apply_op "*" [arg1, arg2] = arg1 * arg2
apply_op "/" [arg1, arg2] = div arg1 arg2

更改应用程序操作可能会有所帮助。下面是两个示例:

apply_op “+” xs = sum xs
apply_op “-“ [x] = -x
apply_op “-“ (x:xs@(_:_)) = x - sum xs

最新更新