Search code examples
haskellfunctional-programmingguard

Rounding Negative Numbers in Haskell Using a Guard


I'm new to Haskell, so I don't quite know how to manipulate the order of operations in a guard or put more constrictions on my 'where' expression in a guard. Here is my first program in Haskell, in which there is some mythical marking scheme that needs to be followed, and it returns you your letter grade. It works perfectly for all non-negative inputs, but the round function seems to fail on negative inputs. Here is my code:

roundMark :: Float -> Integer
roundMark mark
    | mark2 < 0 = 0
    | mark2 > 100 = 100
    | otherwise = mark2
    where mark2 = round mark

letterGrade :: Float -> Char
letterGrade mark 
    | newMark < 48 = 'F'
    | newMark >= 48 && newMark < 65 = 'C'
    | newMark >= 65 && newMark < 79 = 'B'
    | otherwise = 'A'
    where newMark = roundMark mark

For negative inputs, I get the error

No instance for (Num (Float -> Char)) arising from a use of ‘-’
        (maybe you haven't applied a function to enough arguments?)

I'm wondering if there is a way to either put a restriction on my where expression to return 0 for negative inputs before trying to use the round function, or if I can put my guard in a conditional.


Solution

    1. round is "bankers rounding" or "round to even" but you probably (?) want integer truncation such as floor.

    2. What is the purpose of rounding in this case? a negative number is still less than 48 and will still result in an F just like the value 0.

    3. If you want to round all negatives to zero, and not just negative mark2 to zero then just use the right variable:

    .

    roundMark :: Float -> Integer
    roundMark mark
        | mark < 0 = 0      -- See this line, use `mark` vs `mark2`.
        | mark2 > 100 = 100
        | otherwise = mark2
        where mark2 = round mark