我正在尝试在哈斯克尔中制作一个计算器。我已经做到了可以接受两个参数的程度。但是我被困在一个可能需要两个以上论点的地步上。例如,输入类型为 (+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