【问题标题】:Haskell: Need Enlightenment with Calculator programHaskell:需要计算器程序的启蒙
【发布时间】:2013-02-09 08:53:27
【问题描述】:

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

>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)

//实际上比上面更复杂

我不知道如何在 Haskell 中进行编程。我现在能想到的就是将命令行读取为字符串,将其解析为令牌数组。也许通过数组,检测诸如“var”、“def”之类的关键字,然后调用函数 var、def,它们将变量/函数存储在 List 或类似的东西中。但是,我如何存储数据以便以后在计算中使用它们呢?

我也是在正确的轨道上,因为我实际上很困惑下一步该做什么? :(

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

【问题讨论】:

  • 你可以用lex,对吧?
  • 编写您自己的小型解析器组合库!这会很有趣,你会学到很多关于单子和应用函子的知识:)

标签: haskell calculator


【解决方案1】:

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

您应该首先定义一些数据结构,这样您就可以计算出您将要处理什么样的事情。比如:

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]

首先,只需将内容解析(标记化然后再解析标记)到Command,然后决定如何处理它。

表达比较容易。您假设您已经拥有所有需要的定义(Environment),然后只需查找任何变量或进行添加或其他操作。

定义有点棘手。一旦决定了要创建什么新定义,就需要将其添加到环境中。你如何做到这一点取决于你如何准确地遍历这些行,但是你需要将新环境从解释器传递回获取下一行并在其上运行解释器的东西。比如:

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 需要在您创建的环境中查找内容,因此您可能还需要一个函数来查找哪个Definition 对应于给定的Name(或抱怨没有一个)。

您应该做出的其他一些决定:

  • 当有人试图重新定义变量时我该怎么办?
  • 如果我在函数定义中使用了这些变量之一怎么办?我是否在创建或使用函数定义时对其进行评估?

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

【讨论】:

  • 谢谢,当用户重新定义变量时,我需要处理这种情况。你能进一步解释一下数据和类型的使用吗?我认为当声明一个变量/函数时,我需要存储它的名称、参数和表达式。因此我声明了一个新类型: type VariableDef Name [Parameter] Value = (Name,[Parameter],Value) 问题是什么时候使用“type”,什么时候使用“data”?我是否需要为每种类型(即参数、值等)进行定义,因为它们是新的?
  • 您为type 提供的语法是错误的:您不需要您的类型同义词来拥有参数,只需type VariableDef = (Name, [Parameter], Value) 就可以了。何时使用typedata——在这种情况下,这并不重要,但我更喜欢datatype 所做的只是为某些元组类型创建同义词。您可以传入不是变量定义的元组,并且可以很好地进行类型检查。定义新的数据类型可确保不会发生这种情况。我不明白你的最后一个问题。显然你不能使用你没有定义的类型。
  • 哦,我的意思是例如:数据定义 = DefVar 名称表达式 | DefFunc 名称 [名称] 表达式。我们需要定义 DefVar、DefFunc、Name、Expression 吗?
  • 数据声明的形式为data TypeName = ConstructorName ParameterType1 ParameterType2 ... | OtherConstructor MoreTypes ...。构造函数的参数必须是在别处声明的类型,但构造函数本身是由data 声明创建的。所以DefVarDefFunc 不需要已经存在。
【解决方案2】:

首先,你可以从这个tutorial for haskell programming学到很多东西

您需要使用 .hs 在另一个文档中编写您的函数
您可以从编译器加载文件并使用您创建的所有函数
例如

plus :: Int -> Int  -- that mean the function just work with a number of type int and return Int
plus x y = x + y    -- they receive x and y and do the operation 

【讨论】:

  • 嗨,我知道 Haskell 的基础知识,因为这是我的 Haskell 入门课程中的作业。实际上,它是否比编写一个函数来计算两个数字更复杂。用户将根据需要对尽可能多的变量执行任何类型的计算。如果他想计算 a+b/c*d-e 怎么办?此外,用户需要能够将数字存储在变量中,而不仅仅是将直接数字提供给程序(如我上面给出的示例)。
  • +1 内容。我喜欢你的帖子。你有很多贡献。花一点时间考虑如何应用你的洞察力。尝试少猜多解。需要真正的投资,但我希望你坚持下去。 chag semeyach。
  • 我希望可以,问题是时间有限,我只有不到 1 周的时间来完成这项任务。此外,对我来说,用 Haskell 编写程序相当于用外来语言写论文。我需要学习所有新的语法和词汇:(
  • 如果有人需要所有功能的帮助,那么好的部分是基于 lisp 功能。和 lisp 有更多信息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-04
  • 1970-01-01
  • 2012-10-03
  • 2023-03-13
  • 1970-01-01
  • 1970-01-01
  • 2010-09-19
相关资源
最近更新 更多