Haskell problems in a RPN caculator implementation - haskell

I'm trying to implement a RPN caculator in Haskell. It is an exercise from Learn You a Haskell.
Here's my code:
import Data.List
solveRPN :: String -> Int
solveRPN str = head $ foldl putStack [] (words str)
where putStack accumulator token
| token == "+" = pFunction (+)
| token == "-" = pFunction (-)
| token == "*" = pFunction (*)
| token == "/" = pFunction (`div`)
| otherwise = accumulator ++ [read token :: Float]
where pFunction function = (int $ init accumulator) ++ [function argu1 argu2]
argu1 = last accumulator
argu2 = last $ init accumulator
The function solveRPN first split a string into tokens. (ex:"4 3 2 + *"->["4","3","2","+","*"])
Then, one by one tokens are pushed into a stack. If it meets an operator, the last two items in the stack are processed by the operator and the value yielded is then put back into the stack. When the whole list is traversed, there's only one item left in the stack, and that's the answer.
There are some problems here:
In (int $ init accumulator) I want to cancel the last two elements in the stack. Is there any alternative to (int $ init accumulator)?
The code can't pass the compilation. GHC said "parse error on input ("
on this line: | token == "/" = pFunction (div). I suspect the problem might come from pFunction. Its parameter is an operator(or can I call it a function?) and I'm not sure if "function as the parameter of a function" is legal in Haskell. Is this legal? Is there any alternative?
I did some experiments in GHCi and found something strange:
Prelude> let plus = (+)
Prelude> :t (+)
(+) :: Num a => a -> a -> a
Prelude> :t plus
plus :: Integer -> Integer -> Integer
How come the type of plus is different from the type of (+)?
Thanks for your attention and patience. (:

In (int $ init accumulator)
Did you mean init $ init accumulator? That being said, you could write your own dropLast2 function, which does the same as init . init but traverses the list only once, something like
dropLast2 :: [a] -> [a]
dropLast2 [] = []
dropLast2 [_] = []
dropLast2 [_,_] = []
dropLast2 (x:xs) = x : dropLast2 xs
The code can't pass the compilation.
| token == "/" = pFunction (`div`)
You're using backticks (`) in order to use functions with two arguments as infix functions. However, by using parenthesis around div you try to cancel it right away, which is both a little bit off and a parser error. Simply use
| token == "/" = pFunction div
instead. However, there's one major thing of. div's type is
div :: Integral a => a -> a -> a
However, your accumulator is list of Float. div cannot possibly work on those. However, Float is an instance of the Fractional class, so you can simply use (/):
(/) :: Fractional a => a -> a -> a
and therefore get
| token == "/" = pFunction (/)
I did some experiments in GHCi and found something strange
(+) is part of the Num class. Your plus isn't part of any function, and GHC tries to infer its type. And then monomorphism restriction kicks in. See Type error while writing max function for further information.

Regarding your first question:
I get the impression that you are using lists the wrong way around. If you push an element on the stack, you should prepend it to the list using the : operator. Popping the top two elements then becomes drop 2 stack, which is much nicer, I think.
Doing it this way would also be more efficient, since : is a constant time operation while ++ is linear in the size of the first argument (i.e. your stack's size).

Related

Erroneous use of simple Haskell function

I'm learning Haskell and there's a lot of type-checking that seems completely nonsensical to me. I have written a simple function to count the number of occurrences of a given element in a given list, as such:
-- Count the number of occurrences of an element in a list.
countOcc :: (Eq a) => [a] -> a -> Int
countOcc xs x = length $ filter (== x) xs
Now, using this explicitly with calls such as:
countOcc "str" 's'
This executes fine, and returns correctly. However, this causes an error:
countOcc "str" "str"!!0
I haven't the foggiest why this should cause an error. "str"!!0 gives 's', a Char, which is exactly the same type passed in the second parameter of the first call.
I'm sure there are some nuances to Haskell's type system that I'm overlooking, or haven't broached yet. Ideally, I'd like to know why this is erroneous and furthermore, I'd like to know, according to Haskell's ideology, why it should be erroneous.
The following works fine:
countOcc :: (Eq a) => [a] -> a -> Int
countOcc xs x = length $ filter (== x) xs
main = print $ countOcc "str" ("str"!!0) -- 1
As far as I know, function applictaion has the highest precedence; although !! has precedence level of 9, it is still lower than function application.

Haskell: Parse error in pattern x ++ xs

Doing the third of the 99-Haskell problems (I am currently trying to learn the language) I tried to incorporate pattern matching as well as recursion into my function which now looks like this:
myElementAt :: [a] -> Int -> a
myElementAt (x ++ xs) i =
if length (x ++ xs) == i && length xs == 1 then xs!!0
else myElementAt x i
Which gives me Parse error in pattern: x ++ xs. The questions:
Why does this give me a parse error? Is it because Haskell is no idea where to cut my list (Which is my best guess)?
How could I reframe my function so that it works? The algorithmic idea is to check wether the list has the length as the specified inde; if yes return the last elemen; if not cut away one element at the end of the list and then do the recursion.
Note: I know that this is a really bad algorithm, but it I've set myself the challenge to write that function including recursion and pattern matching. I also tried not to use the !! operator, but that is fine for me since the only thing it really does (or should do if it compiled) is to convert a one-element list into that element.
Haskell has two different kinds of value-level entities: variables (this also includes functions, infix operators like ++ etc.) and constructors. Both can be used in expressions, but only constructors can also be used in patterns.
In either case, it's easy to tell whether you're dealing with a variable or constructor: a constructor always starts with an uppercase letter (e.g. Nothing, True or StateT) or, if it's an infix, with a colon (:, :+). Everything else is a variable. Fundamentally, the difference is that a constructor is always a unique, immediately matcheable value from a predefined collection (namely, the alternatives of a data definition), whereas a variable can just have any value, and often it's in principle not possible to uniquely distinguish different variables, in particular if they have a function type.
Yours is actually a good example for this: for the pattern match x ++ xs to make sense, there would have to be one unique way in which the input list could be written in the form x ++ xs. Well, but for, say [0,1,2,3], there are multiple different ways in which this can be done:
[] ++[0,1,2,3]
[0] ++ [1,2,3]
[0,1] ++ [2,3]
[0,1,2] ++ [3]
[0,1,2,3]++ []
Which one should the runtime choose?
Presumably, you're trying to match the head and tail part of a list. Let's step through it:
myElementAt (x:_) 0 = x
This means that if the head is x, the tail is something, and the index is 0, return the head. Note that your x ++ x is a concatenation of two lists, not the head and tail parts.
Then you can have
myElementAt(_:tl) i = myElementAt tl (i - 1)
which means that if the previous pattern was not matched, ignore the head, and take the i - 1 element of the tail.
In patterns, you can only use constructors like : and []. The append operator (++) is a non-constructor function.
So, try something like:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = ...
There are more issues in your code, but at least this fixes your first problem.
in standard Haskell pattern matches like this :
f :: Int -> Int
f (g n 1) = n
g :: Int -> Int -> Int
g a b = a+b
Are illegal because function calls aren't allowed in patterns, your case is just a special case as the operator ++ is just a function.
To pattern match on lists you can do it like this:
myElementAt :: [a] -> Int -> a
myElementAt (x:xs) i = // result
But in this case x is of type a not [a] , it is the head of the list and xs is its tail, you'll need to change your function implementation to accommodate this fact, also this function will fail with the empty list []. However that's the idiomatic haskell way to pattern match aginst lists.
I should mention that when I said "illegal" I meant in standard Haskell, there are GHC extensions that give something similar to that , it's called ViewPatterns But I don't think you need it especially that you're still learning.

How can I replace generators if I need only one result?

I'm playing with Haskell for first time.
I've created function that returns first precise enough result. It works as expected, but I'm using generator for this. How can I replace generator in this task?
integrateWithPrecision precision =
(take 1 $ preciseIntegrals precision) !! 0
preciseIntegrals :: Double -> [Double]
preciseIntegrals precision =
[
integrate (2 ^ power) pi | power <- [0..],
enoughPowerForPrecision power precision
]
You can use the beautiful until function. Here it is:
-- | #'until' p f# yields the result of applying #f# until #p# holds.
until :: (a -> Bool) -> (a -> a) -> a -> a
until p f x | p x = x
| otherwise = until p f (f x)
So, you can write your function like this:
integrateWithPrecision precision = integrate (2 ^ pow) pi
where
pow = until done succ 0
done pow = enoughPowerForPrecision pow precision
In your case, you do all the iteration and then compute a result just once. But until is useful even when you need to compute a result at each step - just use an (iter, result) tuple and then just extract the result at the end with snd.
It seems like you want to check higher and higher powers until you get one that satisfies a requirement. This is what you could do: First you define a function to get enough power, and then you integrate using that.
find gets the first element of a list that satisfies a condition – like being enough of a power! Then we need a fromJust to get the actual value from that. Please note that almost always, fromJust is a terrible idea to have in your code. However, in this case the list is infinite, so we will have troubles with infinite loops long before fromJust is able to crash the program.
enoughPower :: Double -> Int
enoughPower precision =
fromJust $ find (flip enoughPowerForPrecision precision) [0..]
preciseIntegrals :: Double -> Double
preciseIntegrals precision = integrate (2^(enoughPower precision)) pi
The function
\xs -> take 1 xs !! 0
is called head
head [] = error "Cannot take head of empty list"
head (x:xs) = x
Its use is somewhat unsafe, as shown it can throw an error if you pass it an empty list, but in this case since you can be certain your list is non-empty it's fine.
Also, we tend not to call these "generators" in Haskell as they're not a special form but are instead a simple consequence of lazy evaluation. In this case, preciseIntegrals is called a "list comprehension" and [0..] is nothing more than a lazily generated list.

Beginner Haskell problems (No instance for ... arising from)

I recently started learning Haskell and I'm trying to rewrite something I did for an interview in python in Haskell. I'm trying to convert a string from camel case to underscore separated ("myVariableName" -> "my_variable_name"), and also throw an error if the first character is upper case.
Here's what I have:
import qualified Data.Char as Char
translate_java :: String -> String
translate_java xs = translate_helper $ enumerate xs
where
translate_helper [] = []
translate_helper ((a, num):xs)
| num == 1 and Char.isUpper a = error "cannot start with upper"
| Char.isUpper a = '_' : Char.toLower a : translate_helper xs
| otherwise = a : translate_helper xs
enumerate :: (Num b, Enum b) => [a] -> [(a,b)]
enumerate xs = zip xs [1..]
I realize It's pretty likely I'm going about this in a weird way, and I'd love advice about better ways to implement this, but I'd like to get this to compile as well. Here's the error I'm getting now:
Prelude> :r
[1 of 1] Compiling Main ( translate.hs, interpreted )
translate.hs:4:20:
No instance for (Num
(([Bool] -> Bool) -> (Char -> Bool) -> Char -> t))
arising from a use of `translate_helper' at translate.hs:4:20-35
Possible fix:
add an instance declaration for
(Num (([Bool] -> Bool) -> (Char -> Bool) -> Char -> t))
In the first argument of `($)', namely `translate_helper'
In the expression: translate_helper $ enumerate xs
In the definition of `translate_java':
translate_java xs
= translate_helper $ enumerate xs
where
translate_helper [] = []
translate_helper ((a, num) : xs)
| num == 1 and Char.isUpper a
= error "cannot start with upper
"
| Char.isUpper a
= '_' : Char.toLower a : transla
te_helper xs
| otherwise = a : translate_help
er xs
Failed, modules loaded: none.
Any explanation of what's going on here would be great. I really don't understand where "(Num (([Bool] -> Bool) -> (Char -> Bool) -> Char -> t))" is coming from. I'd think the type declaration for translate_helper would be something like [(a,b)] -> [a]?
You have to replace and by &&. The first one is a function (prefix) that receives a list of boolean values and calculates an and of them all. The second one is a true logical and. The error message is a little bit confusing though. Whenever I get such a strange error message, I usually start to annotate my code with type signatures. Then the compiler is able to give you a more detailed description of what went wrong.
Others have mentioned that you should use (&&) instead of and, so I'll answer your other question: no, I don't think you're going about this in a weird way.
But... I do think it can be even more elegant!
translate_java (x:xs) | isUpper x = error "cannot start with an upper"
translate_java xs = concatMap translate xs where
translate x = ['_' | isUpper x] ++ [toLower x]
There's a few interesting things going on here:
The special case is checked straight away. Don't wait until you're recursing to do this!
The concatMap function is really handy in a lot of cases. It's just a map followed by a concat. If I were writing this myself, I'd probably use xs >>= translate instead.
That ['_' | isUpper x] is a list comprehension; this is a cute idiom for making a list with either 0 or 1 elements in it, depending on whether a predicate holds.
Other than that, the code should be fairly self-explanatory.
The problem is this:
| num == 1 and Char.isUpper a = ...
and is not an infix operator; rather it is a function:
and :: [Bool] -> Bool
So it is interpreting 1 and Char.isUpper a as applying three arguments to the "function" 1. Use && instead.
The error message comes from the way numerals are interpreted. A numeral, say, 1 is actually polymorphic; the specific type it gets depends on the type that is needed. That's why you can say x+1 and it will work whether x is an integer or a double or whatever. So the compiler inferred that the type of 1 needs to be a three-argument function, and then tried to find a numeric type matching that so it could convert 1 into that type (and, naturally, failed).
Here's my solution. It's not as masterful as the answer Daniel Wagner gave using concatMap and the list comprehension, but it's perhaps easier to understand for the beginner.
conv :: String -> String
conv [] = []
conv s#(x:xs) = if Char.isUpper x
then error "First character cannot be uppercase"
else change s
change :: String -> String
change [] = []
change (x:xs) = if Char.isUpper x
then '_' : Char.toLower x : change xs
else x : change xs
The function conv really just checks your criterion that the first character must not be uppercase, and if it isn't it hands over the string to the function change, which does the work. It goes through all the characters one by one, building a list, and if the character is uppercase, it adds an underscore followed by the lowercase version of the character, otherwise if the character is already lowercase it just adds it as it is.

Using Either correctly

So I have the following function:
chk2 :: [(Integer,Integer)] -> Either [(Integer,Integer)] (Integer,Integer)
chk2 i#((n,_):_)
| chkp (prod $ lgst i)==True = Right $ lgst i
| lgst i==i!!0 = Left $ chk2 $ (4-2,4-2):next i
| otherwise = Left $ chk2 $ next i
where prod (a,b) = a*b
lgst = foldl1 (\(a,b) (c,d) -> if prod (a,b) > prod (c,d) then (a,b) else (c,d))
next t = map (\(a,b) -> if (a,b)==lgst t then (a-1,b+1) else (a,b)) t
along with this error:
runhugs: Error occurred
ERROR "4/4.hs":14 - Type error in explicitly typed binding
*** Term : chk2
*** Type : [(Integer,Integer)] -> Either (Either [(Integer,Integer (Integer,Integer)) (Integer,Integer)
*** Does not match : [(Integer,Integer)] -> Either [(Integer,Integer)] (Integer,Integer)
I'm trying to get this function to either end up with an (a,b) i.e. first guard or [(a,b)] i.e. the latter two guards. The basic problem is in the latter two guards.. if I take out the recursion, everything works fine, but I'm not sure how to define the type signature when returning the function itself.
The problem is with how you recurse.
According to the type of chk2, chk2 $ next i is of type Either [(Integer,Integer)] (Integer,Integer). Left is of type b -> Either b a, so Left $ chk2 $ next i is of type Either (Either [(Integer,Integer)] (Integer,Integer)) a for some unspecified type a.
Left $ chk2 $ (4-2,4-2):next i has a similar problem.
To fix, you need to decide how you want to handle the recursive value.
Easy fix:
| lgst i==i!!0 = chk2 $ (4-2,4-2):next i
| otherwise = chk2 $ next i
However, I doubt this is what you want, since it means all your results will be Right.
I'm not sure how to do what you want, because I'm not sure what you want.
What does a list result mean? What does a non-list result mean?
What you probably want to do is pattern match the result of the recursion, transforming Right pair -> Left [pair], perhaps appending some other result to the front.
As an example, I'll construct a recursive function with a similar type signature. Let foo be a function that takes a list of integers, and:
if the first element of the list is the maximum of the whole list, returns that element
otherwise, return a subsequence of the list, where each is the maximum of all the elements between it and the next element in the subsequence (or the end)
To do this:
foo :: [Integer] -> Either [Integer] Integer
foo [] = Left []
foo (x:xs) = case foo xs of
Left ys -> if all (<=x) ys
then Right x
else let (_,ys') = break (>x) ys in Left (x:ys')
Right y -> if x >= y
then Right x
else Left [x,y]
Note how I use case to pattern match on the result of the recursive call to foo.
To solve Euler #4, yours seems to be a very awkward style for Haskell. It's usually a bad idea to try and "port" code from other languages into Haskell, since the paradigm for Haskell is so very different.
You'll find a very clean, sensible solution to Euler #4 that uses list comprehensions at the Haskell Wiki. Certainly not the only solution, but it is at least 20x as readable as your current code. No offense.
I (and tons of other Haskellers) highly recommend Learn You a Haskell and Real World Haskell for learning how to approach problems the Haskell way, which in my experience is usually to create small, simple helper methods and compose them into a solution.

Resources