Well, if you are at all familiar with (or wanted to learn about) the Maybe
type, I would suggest you use that. A brief synopsis:
data Maybe a = Nothing | Just a
Which means that a Maybe Int is either Nothing or or Just an int.
If you were to got this path, then your p function should have type [String] ->
[Maybe Int] - which means that either the calculator has a response (Just 22 or
Just 6 or Just whatever) or something went wrong (invalid input) and it gave
Nothing.
So in your case, you'd get:
> Parsing> p ["2*34/3","2+3","2*(6 / 2)",""]
> [Just 22,Just 5,Just 6,Nothing]
Which really clearly demonstrates what you are trying to communicate (and
importantly doesn't cause the whole program to stop running when it sees a bad
input).
Then in the eval function, the error cases would result in Nothing, and the
good cases would result in Just n.
On Jun 27, 2011, at 12:09 PM, Stoyan Peev wrote:
> Yeah, that really helped me :))
>
> Finally i got the results i wanted :
>
> Main> p ["2*34/3","2+3","2*(6/2)"]
> [22,5,6]
>
>
> There is only one more question i have about this. I have already
> written 2 error captures, but they don't really apply to the task i
> have. Here are my error captures:
>
> [(_,out)] -> error ("неопределено")
> [] -> 0
>
> and here is the result
>
> Parsing> p ["2*34/3","2+3","2*(6 / 2)",""]
> [22,5,6,0]
>
> It's ok for me, but i have to make it, not showing anything if there are
> blanks.
> I suggest i had to make some checking in the caller function before
> calling the "eval" funcition.
> Also somehow i have to check the syntax of the string and if it is
> like "=x", the result should be "x= previous string"
>
> Probably i have to user "where" for the caller function or some if cases :?
>
>
>
>
> 2011/6/27 Daniel Patterson <[email protected]>:
>> so think about the high level design for a second, and let that guide the
>> types. then the types should guide the code.
>>
>> p, which I assume is the top level evaluation, is supposed to take a list of
>> strings, and produce a list of integers (the result of evaluating the
>> expression), right? So it should have type p :: [String] -> [Int].
>>
>> Now the base case is obvious - if you are given an empty list of strings,
>> then you should give back an empty list of results.
>>
>> The recursive case is a little more complicated - the idea with simple
>> recursion is that the recursive case should eventually land you at the base
>> case, which will stop the recursion. With lists, this usually means that
>> each application of the recursive case should call itself on the rest of the
>> list, and somehow process the first element of the list (it doesnt have to
>> be this way, but often is).
>>
>> So in your case, the recursive case should be: evaluate the first element of
>> the list, and then call the whole function on the rest of the list. You can
>> check this mentally by using a couple examples. In the case of a one element
>> list, this means that it will evaluate the first (and only) element of the
>> list, and then call itself on the rest of the list, which is an empty list,
>> which is the bottom case and therefore ends the recursion. On a two element
>> list, this can be checked as well.
>>
>> Now the types should be your best friend. You know that you want:
>>
>> p :: [String] -> [Int]
>>
>> That is from the problem statement.
>>
>> So you write the base case first:
>>
>> p [] = []
>>
>> Now for the recursive case, you know you want to eval the first element, and
>> then call the function on the rest of the list. But since you need to return
>> a list eventually, then you need to return a list in this function. You know
>> that calling the function recursively will result in a list (the type
>> guarantees that), so if you've evaluated the first element of a list,
>> resulting in an Int, and you have a list of Int's that is the rest of the
>> list, how do you combine those? Well, put the element at the beginning of
>> the list!
>>
>> p (x:xs) = (eval p) : (p xs)
>>
>>
>> Now this is a really really common pattern - do the same thing to every
>> element of a list. The first thing in haskell to do if you think that what
>> you are doing might already exist in some generalized form is to try to
>> describe what the function is that you want. So in our case, you want a
>> function that takes another function and applies it to every element in the
>> list. This function would have type:
>>
>> (a -> b) -> [a] -> [b]
>>
>> In your case the (a -> b) is String -> Int (the function eval), the [a] is
>> [String], [b] is [Int]. Now if you take this and search on Hoogle (a haskell
>> search engine:
>> http://haskell.org/hoogle/?hoogle=%28a+-%3E+b%29+-%3E+%5Ba%5D+-%3E+%5Bb%5D
>> ), the first result is a function called map, which does exactly what you
>> want. So you can actually write your whole p function as:
>>
>> p :: [String] -> [Int]
>> p xs = map eval xs
>>
>> Or, if you are okay with partial application, this is equivalent to:
>> p :: [String] -> [Int]
>> p = map eval
>>
>> On Jun 25, 2011, at 3:56 PM, Jack Henahan wrote:
>>
>>> The error in ghci is
>>>
>>> Couldn't match expected type `Int' with actual type `[a0]'
>>> In the expression: []
>>> In an equation for `p': p [] = []
>>>
>>> You've defined p as [String] -> Int, but then your base case is p [] = [].
>>> [] is not an Int. I changed it to 0 and it'll compile, at least, but I'm
>>> not sure if that's the effect you're after.
>>>
>>> http://hpaste.org/48324
>>> Edited code (really just indentation changes and the change from p [] = []
>>> to p [] = 0)
>>>
>>> On Jun 25, 2011, at 3:19 PM, Stoyan Peev wrote:
>>>
>>>> First I am using WinHugs.
>>>>
>>>> that's the code i made so far but it's still not working:
>>>>
>>>> http://hpaste.org/48318
>>>>
>>>>
>>>> Error:
>>>> ERROR file:.\kursovazadacha.hs:36 - Type error in explicitly typed binding
>>>> *** Term : p
>>>> *** Type : [String] -> [a]
>>>> *** Does not match : [String] -> Int
>>>>
>>>>
>>>> I'm still breaking down somewhere ...
>>>>
>>>>
>>>>
>>>> 2011/6/25 Daniel Patterson <[email protected]>:
>>>>> what haskell compiler are you using? And what does the "include" line do?
>>>>>
>>>>> That does not look like a GHC error message (the only compiler I'm
>>>>> familiar with), but it seems like it is saying that you should not have
>>>>> the extra newlines between the function type signature and declaration. -
>>>>> that's only my guess, based on the assumption that the whitespace is
>>>>> being converted to a syntax with explicit semilcolon line terminations.
>>>>>
>>>>> now, looking at the actual code, the type of the parse function is [a] ->
>>>>> [a]. This means that you can parse a list of anything into a list of
>>>>> anything, which doesnt make much sense. This should probably be [String]
>>>>> -> [String] (you are parsing a list of strings to a list of strings,
>>>>> yes?). Now the base case of parse (the first case) makes sense, but look
>>>>> at the second case. parse is being given a list of elements (which you
>>>>> have used pattern matching to decompose, but the whole argument, (x:xs),
>>>>> is a list of elements). You are then passing that, unchanged, to eval.
>>>>> This means that eval must take the same type. Does it? how would you
>>>>> apply eval to each element in that list, instead of just applying it to
>>>>> the whole list?
>>>>>
>>>>> On Jun 24, 2011, at 4:31 PM, Stoyan Peev wrote:
>>>>>
>>>>>> I found the library myself, and i already put the code in that site:
>>>>>>
>>>>>> http://hpaste.org/48277
>>>>>>
>>>>>>
>>>>>>
>>>>>> That's what i have tried to do for making the task by calling the one
>>>>>> string function by another one:
>>>>>>
>>>>>> include kursovazadacha
>>>>>>
>>>>>> parse :: [a] -> [a]
>>>>>>
>>>>>> parse [] = []
>>>>>>
>>>>>> parse (x:xs) = eval (x:xs)
>>>>>>
>>>>>>
>>>>>> The error from the compiler:
>>>>>>
>>>>>> ERROR file:.\list.hs:3 - Syntax error in declaration (unexpected `;',
>>>>>> possibly due to bad layout)
>>>>>>
>>>>>>
>>>>>> On Fri, Jun 24, 2011 at 11:20 PM, Daniel Patterson
>>>>>> <[email protected]> wrote:
>>>>>>> What have you tried to do in order to make it work for the list, and
>>>>>>> what error results? What is confusing about the error message? More
>>>>>>> generally, how could you transform an operation on a single string into
>>>>>>> one that does the same thing to a list of strings? You've probably
>>>>>>> talked about higher order functions in your class - would any of the
>>>>>>> common ones (filter, map, foldr) be helpful here? Would any encapsulate
>>>>>>> what you are trying to do?
>>>>>>>
>>>>>>> If you include these kinds of things, I think you'll find this
>>>>>>> community to be very helpful; without that (showing what your thought
>>>>>>> process is, why it isn't working, what seems confusing about what the
>>>>>>> haskell compiler is telling you, etc), you are not going to get help
>>>>>>> here. People here are very friendly and willing to help people learn;
>>>>>>> this is not a place to come to get an assignment finished :)
>>>>>>>
>>>>>>> Also, could you put the library you are using (I'm assuming that this
>>>>>>> is provided by your university) and the code on somewhere like
>>>>>>> hpaste.org, so that the formatting is not messed up by email, and it is
>>>>>>> syntax highlighted?
>>>>>>>
>>>>>>> On Jun 24, 2011, at 3:57 PM, Stoyan Peev wrote:
>>>>>>>
>>>>>>>> Hello all,
>>>>>>>>
>>>>>>>> I am experiencing some issues to do my course task in university.
>>>>>>>>
>>>>>>>> I have to write a calculator- function in Haskell. 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
>>>>>>>> - 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) and
>>>>>>>> parentheses. Where no brackets, the operations are performed from left
>>>>>>>> to right, but * and / precede the + and -. Implementation of any
>>>>>>>> operation gives integer; in the division rejected the fractional part,
>>>>>>>> if any.
>>>>>>>> Variables have names of one letter - from the Latin small letter. 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"].
>>>>>>>>
>>>>>>>>
>>>>>>>> I say another person have the same task, but he didn't do anything. I
>>>>>>>> started doing this task myself but i get stuck in the middle. Then i
>>>>>>>> started searching for something that could help me and find out you :)
>>>>>>>>
>>>>>>>> The code i have written so far uses the library file "Parsing.lhs"
>>>>>>>> but what i have written is taking those actions that i already
>>>>>>>> described, only for a string. I cannot modify it to work for list of
>>>>>>>> string, and complete the whole task.
>>>>>>>>
>>>>>>>> I'll be glad to finish the task myself, but i am going to need some
>>>>>>>> help.
>>>>>>>>
>>>>>>>> Here is the code i have already written:
>>>>>>>>
>>>>>>>>
>>>>>>>> import Parsing
>>>>>>>>
>>>>>>>> expr :: Parser Int
>>>>>>>> expr = do t <- term
>>>>>>>> do symbol "+"
>>>>>>>> e <- expr
>>>>>>>> return (t+e)
>>>>>>>> +++ do symbol "-"
>>>>>>>> e <- expr
>>>>>>>> return (t-e)
>>>>>>>> +++ return t
>>>>>>>> term :: Parser Int
>>>>>>>> term = do f <- factor
>>>>>>>> do symbol "*"
>>>>>>>> t <- term
>>>>>>>> return (f * t)
>>>>>>>> +++ do symbol "/"
>>>>>>>> t <- term
>>>>>>>> return (f-t)
>>>>>>>> +++ return f
>>>>>>>> factor :: Parser Int
>>>>>>>> factor = do symbol "("
>>>>>>>> e <- expr
>>>>>>>> symbol ")"
>>>>>>>> return e
>>>>>>>> +++ natural
>>>>>>>> eval :: String -> Int
>>>>>>>> eval xs = case (parse expr xs) of
>>>>>>>> [(n,[])] -> n
>>>>>>>> [(_,out)] -> error ("undefined")
>>>>>>>> [] -> error "error"
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Thanks all in advance :)
>>>>>>>>
>>>>>>>> --
>>>>>>>> Best Wishes
>>>>>>>> Stoyan Peev
>>>>>>>>
>>>>>>>> _______________________________________________
>>>>>>>> Haskell-Cafe mailing list
>>>>>>>> [email protected]
>>>>>>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Поздрави,
>>>>>> Стоян Пеев
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Поздрави,
>>>> Стоян Пеев
>>>>
>>>> _______________________________________________
>>>> Haskell-Cafe mailing list
>>>> [email protected]
>>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>
>>> <398E692F.asc>
>>>
>>> _______________________________________________
>>> Haskell-Cafe mailing list
>>> [email protected]
>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
>>
>
>
>
> --
> Поздрави,
> Стоян Пеев
_______________________________________________
Haskell-Cafe mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/haskell-cafe