[Haskell-cafe] Help
Daniel Patterson
lists.haskell at dbp.mm.st
Mon Jun 27 18:22:02 CEST 2011
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 <lists.haskell at dbp.mm.st>:
>> 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 <lists.haskell at dbp.mm.st>:
>>>>> 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
>>>>>> <lists.haskell at dbp.mm.st> 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
>>>>>>>> Haskell-Cafe at haskell.org
>>>>>>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>>>>>
>>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> --
>>>>>> Поздрави,
>>>>>> Стоян Пеев
>>>>>
>>>>>
>>>>
>>>>
>>>>
>>>> --
>>>> Поздрави,
>>>> Стоян Пеев
>>>>
>>>> _______________________________________________
>>>> Haskell-Cafe mailing list
>>>> Haskell-Cafe at haskell.org
>>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>>
>>> <398E692F.asc>
>>>
>>> _______________________________________________
>>> Haskell-Cafe mailing list
>>> Haskell-Cafe at haskell.org
>>> http://www.haskell.org/mailman/listinfo/haskell-cafe
>>
>>
>
>
>
> --
> Поздрави,
> Стоян Пеев
More information about the Haskell-Cafe
mailing list