[Haskell-cafe] Trying to make a calculator

Vo Minh Thu noteed at gmail.com
Mon Jul 18 16:48:32 CEST 2011


2011/7/18 Emanuil Boyanov <emanuilboyanov at gmail.com>:
> Hi guys, I'm new to Haskell, I learn it for couple of months now and we've
> learned only simple functions like map, zip etc. But now my assignment is a
> lot tougher than I thought so I'll need some guidelines. I've googled my
> assignment and I saw a person with the exact assignment so I am gonna copy
> the task then I'm gonna show you what I've done so far.
> Here it is: Make calculator function.
>  The function argument is a list of strings and also form such  list, as
> each string of the argument made definite action.
> - If the string has the form of an arithmetic expression - calculate
> this expression. The string result becomes part of the list-    result.
> If the expression contains a variable which is not assigned value, the
> result is displayed "undefined".
>  - If the string has the form     Name =  value calculated from the last
> expression is assigned to the variable with the corresponding name in the
> list, and in the result list    is formed a string with type     name = ...
>     where the site stands blank corresponding value.     If there is not a
> calculated expression to be assigned to form a string "no value".
> - If the string is non-blank, but there is a species different from the
> above two case, form the string "error".
> - If the string is empty, incl. when it contains only spaces, in the result
> there is  not form a string.     Expressions consist of integers without
> sign variables,
> operations
>    + (Addition), - (subtraction), * (multiplication) and / (divide)
>  In the beginning, end or between the elements of each row can have  spaces
> - they are irrelevant to its correctness.
> Example:
> the list-argument     ["3 +7 / 2", "2 + x", "= s", "2 * s +4", "", "2 + +4 /
> 5"]     function should provide a result-list     ["6", "undefined", "s =
> 6", "16",
> "error"].
> =========
> So what I've done so far is:
> calculator [] = []
> calculator [" "] = []
> calculator [c] = [c]
> calculator (c:" ":cs) = c:calculator cs
> calculator (" ":cs) = calculator cs
> calculator (c:" ":" ":cs) = calculator (c:" ":cs)
> calculator (c:cs)
> | (head c `elem` ['a'..'z']) && (head(tail c) `elem` ['+','-','*','/']) &&
> (last(take (length c-2)c) `elem` ['1','2','3','4','5','6','7','8','9'])  =
>  calculator cs
>         | otherwise = "error":calculator cs
> I try at first to use pattern matching for the blank strings in the first
> list, so that I can get rid off them in the second list. Am I even on the
> right way here?
> I found the "elem" function and I'm trying to check if the first char of the
> string is a letter or a number, then if the second char is one of the
> operations and so on. Problem is that I have no idea how can I check if the
> variable is defined already or how to save a variable and then give that
> variable the new value - is that even possible? :] And another thing `elem`
> [1..9] isn't working - how can I make a single char of a string to hold an
> integer..
> Could you give me some guidelines or at least tell me if I'm on the right
> way here so I can move forward and improve my program.
> Thanks a lot!

Hello,

You should work by smaller steps.

For instance, you can begin by abstracting the syntax. At the very
beginning, you get some strings (a list of statements) and you
transform them in something much simpler to use. Here, there is also
an intermediary step to make things easier.

Let's say you have "  1 + 2 ". You can make things simpler by working
on ["1", "+", "2"]. Here, the problem with blancs is already dealt
with. You just have a list of tokens. Then, to make it simple later on
to differentiate between a number and an operator (and a variable),
you can define your own representation, for instance:

data Token = TNum Int | TOp Op | ...
data Op = Add | Sub | ...

Now the list  ["1", "+", "2"] becomes [TNum 1, TOp Add, TNum 2]. Now
you can use pattern matching on the Token and easily know what you
have.

For your variable assignment problem, you have to provide an
environment, i.e. a mapping between variable name and their value. If
you use a recursive function to evaluate your little language, you can
provide that environement as a supplementary argument.

Try to proceed that way, one step at a time, and come back if you have
any problem.

Cheers,
Thu



More information about the Haskell-Cafe mailing list