2
votes

I got a question regarding Haskell, I tried to make a function to half an even number only in a list and return the final list with only the even number(s) got modified(got halved) with the rest of the element remained untouched.

But when I try to compile my code, I gave an error saying that "error: parse error on input ‘if'" and I couldn't find the solution for it.

halfEvens :: [ Int ] -> [ Int ]
halfEvens xs = [x|x<-xs]
                if x mod 2 == 0
                the x = x / 2
                else
                x = x
3
Sorry because my code is a bit messed up. So what should I do in order to make my function work as what I want ? Do you have any recommendation ? - Wandy

3 Answers

4
votes

Your code has multiple issues:

  • [x|x<-xs] doesn't do anything useful. This will just evaluate to xs.
  • If you're using mod as an infix operator, it needs backticks around it
  • You can't reassign variables. then x = x / 2 and x = x are illegal in Haskell.

The main problem though is the fact that you have an empty list comprehension ([x|x<-xs]), with an if expression just kind of floating underneath it. I believe your intent was to put the if inside of the comprehension. Something like:

halfEvens :: [Int] -> [Int]
halfEvens xs = [if x `mod` 2 == 0 then x `quot` 2 else x | x <- xs]

Changes:


main = do
  putStrLn . show $ halfEvens [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]

[1,1,3,2,5,3,7,4,9,0]

Your code shows some serious misunderstandings of Haskell though. I recommend sitting down with a good book and trying out all the examples. Haskell is not an easy language. Don't try to rush through it.

3
votes

So, you want to apply a function that halves even numbers, but leaves odd numbers alone. We can write a function to perform this transform on a single Int, using even from the prelude:

halfEven :: Int -> Int
halfEven x | even x = x `div` 2
           | otherwise = x

Now we can map this function over a list of Int:

halfEvens :: [Int] -> [Int]
halfEvens xs = map halfEven xs

Or go point free:

halfEvens = map halfEven

Or use a list comprehension:

halfEvens xs = [halfEven x | x <- xs]
2
votes

Keeping as much of your original code/intent as possible,

halfEvens xs = [x | x <- xs, x <- [   -- instead of x = ...
                 if x `mod` 2 == 0
                   then {- x = -} x `div` 2
                   else {- x = -} x ]]

Its type gets deduced as halfEvens :: Integral t => [t] -> [t].

Funny thing about it is that we're allowed to use the same variable name there, with the x <- [...] construct; it just gets shadowed. But it's OK, since we're only interested in the new value anyway. That way we treat it mentally as a variable "update", although there's no updating variables in Haskell, of course.