Haskell:需要计算器程序启发 [英] Haskell: Need Enlightenment with Calculator program

查看:118
本文介绍了Haskell:需要计算器程序启发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个任务是在Haskell中创建一个计算器程序。例如,用户可以通过命令行来使用计算器,例如:

 > var cola = 5; //定义一个随机变量
>可乐* 2 + 1;
(print 11)
> var pepsi = 10
> coca>百事可乐;
(print false)
> def coke(x,y)= x + y; //定义一个随机函数
>可乐(可乐,百事可乐);
(print 15)

//实际上它比上面更复杂



我不知道如何在Haskell中编程。我现在所能想到的只是将命令行读为String,将其解析为一个令牌数组。也许要通过数组,检测关键字如var,def,然后调用函数var,def将变量/函数存储在List中或类似的东西中。但是,我如何存储数据,以便以后可以在我的计算中使用它们?



另外我在正确的轨道上,因为我其实很困惑下一步该怎么做? :(



* 另外,我不允许使用Parsec *

解决方案

它看起来像你有两种截然不同的输入:声明(创建新变量和函数)和表达式(计算事物)。 b
$ b

您应该首先定义一些数据结构,以便您可以计算出将要处理的事情,例如:

  data Command = Define Definition | Calculate Expression | Quit 
type Name = String
data Definition = DefVar Name Expression | DefFunc Name [Name] Expression
- 或者,将变量实现为零参数函数
- 并合并这些情况
data Expression = Var Name |添加表达式表达式| - ...其他东西
类型Environment = [定义]

首先,解析(tokenise然后解析令牌,也许)填入命令

表达式比较容易。你假设你已经拥有了所有你需要的定义(一个 Environment ),然后查找任何变量或者添加或者其他的东西。



定义有点棘手。一旦你决定要制定新的定义,你需要将它添加到环境中。你如何做到这一点取决于你如何遍历线条,但是你需要将新的环境从解释器转回到取得下一行并在其上运行解释器的东西。例如:

  main :: IO()
main = mainLoop emptyEnv
其中
emptyEnv = []

mainLoop :: Environment - > IO()
mainLoop env = do $ b $ str< - getLine
case parseCommnad str of
Nothing - >做
putStrLn解析失败!
mainLoop env
只需退出 - >做
return()
Just(Define d) - >做
mainLoop(d:env)
Just(Calculate e) - >做
putStrLn(计算环境)
mainLoop env

- 真正的肉:
parseCommand :: String - >可能命令
calc :: Environment - >表达式 - >字符串 - 或整数或其他适当类型

calc 需要在你创建的环境中查看一些东西,所以你可能还需要一个函数来查找哪一个定义对应给定的名称(或者抱怨没有)。



您应该做的其他决定:




  • 如果有人试图重新定义变量,该怎么办?

  • 如果我在其中一个变量函数的定义?当创建或使用函数定义时,我是否评估一个函数定义?



这些问题可能会影响上述程序的设计,但我会留给你解决问题。


I have an assignment which is to create a calculator program in Haskell. For example, users will be able to use the calculator by command lines like:

>var cola =5; //define a random variable
>cola*2+1;
(print 11)
>var pepsi = 10 
>coca > pepsi;
(print false)
>def coke(x,y) = x+y;  //define a random function
>coke(cola,pepsi);
(print 15)

//and actually it's more complicated than above

I have no clue how to program this in Haskell. All I can think of right now is to read the command line as a String, parse it into an array of tokens. Maybe go through the array, detect keywords such "var", "def" then call functions var, def which store variables/functions in a List or something like that. But then how do I store data so that I can use them later in my computation?

Also am I on the right track because I am actually very confused what to do next? :(

*In addition, I am not allowed to use Parsec!*

解决方案

It looks like you have two distinct kinds of input: declarations (creating new variables and functions) and expressions (calculating things).

You should first define some data structures so you can work out what sort of things you are going to be dealing with. Something like:

data Command = Define Definition | Calculate Expression | Quit
type Name = String
data Definition = DefVar Name Expression | DefFunc Name [Name] Expression
-- ^ alternatively, implement variables as zero-argument functions
-- and merge these cases
data Expression = Var Name | Add Expression Expression | -- ... other stuff
type Environment = [Definition]

To start off with, just parse (tokenise and then parse the tokens, perhaps) the stuff into a Command, and then decide what to do with it.

Expressions are comparatively easy. You assume you already have all the definitions you need (an Environment) and then just look up any variables or do additions or whatever.

Definitions are a bit trickier. Once you've decided what new definition to make, you need to add it to the environment. How exactly you do this depends on how exactly you iterate through the lines, but you'll need to pass the new environment back from the interpreter to the thing which fetches the next line and runs the interpreter on it. Something like:

main :: IO ()
main = mainLoop emptyEnv
 where
  emptyEnv = []

mainLoop :: Environment -> IO ()
mainLoop env = do
  str <- getLine
  case parseCommnad str of
    Nothing -> do
      putStrLn "parse failed!"
      mainLoop env
    Just Quit -> do
      return ()
    Just (Define d) -> do
      mainLoop (d : env)
    Just (Calculate e) -> do
      putStrLn (calc env e)
      mainLoop env

-- the real meat:
parseCommand :: String -> Maybe Command
calc :: Environment -> Expression -> String -- or Integer or some other appropriate type

calc will need to look stuff up in the environment you create as you go along, so you'll probably also need a function for finding which Definition corresponds to a given Name (or complaining that there isn't one).

Some other decisions you should make:

  • What do I do when someone tries to redefine a variable?
  • What if I used one of those variables in the definition of a function? Do I evaluate a function definition when it is created or when it is used?

These questions may affect the design of the above program, but I'll leave it up to you to work out how.

这篇关于Haskell:需要计算器程序启发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆