Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typing in Haskell: Passing a number that looks fractional, but will always be an Integer (type aliasing)

Tags:

c

haskell

typing

I'm currently learning Haskell using the Gentle Introduction to Haskell website, and I took a break halfway into section 4 to test my knowledge. I'm trying to implement a "greatest prime in a composite number" function that I used when I was working in C, but I'm having trouble with Haskell's typing system. I'm trying to pass a number that looks like it's a fractional Int, but because I've used modulus to check if it's divisible, I know will evaluate to an Int. Here's the context:

The C: I've super-commented it in case it's unclear, but the code should be fairly straightforward.

int highest(long currDom, long lastLargest, long currMax)
/* This is a recursive function that starts at the lowest prime number, 2,
 * and divides into currMax. If a division operation is even - modulus returns 0 -
 * then the prime number in the division is saved as "lastLargest," and the
 * function calls itself again, with MAX now passed as MAX/lastLargest. Otherwise,
 * the function is called with currMax remaining the same value, and the
 * current denominator to try (currDom) incremented by one.
 */
{
    if (currDom > currMax)   //end result - when the current value of MAX is less
        return lastLargest;  //than the value of the denominator we're trying, we're done
    else
    {
        if (currMax % currDom == 0)      //if modulus succeeds, try again with Max/currDom
            return highest(currDom, currDom, currMax/currDom);  //denominator is kept the same incase
        else                                                    //it goes into MAX multiple times -e.g. 2 into 8 
            return highest(currDom+1, lastLargest, currMax);    //else, try the next denominator.
    }

}

If you were looking for the highest in 10, for example, you would call this by saying "highest(10, 2, 1)" - you're looking for the highest prime in 10, starting at 2, and the current highest prime in the number is 1. It would return when it tried the number 5 as a divisor for the second time, and saw that curDom is now 1.

The problem is that when I try this in Haskell, on the fourth line in my code, I run into an issue with passing the number divided by a prime that goes into it - it appears to be a fractional Int, but because I've already checked with modulus, I know it's going to resolve to a regular Int. Here's the code I'm working with:

greatestPrime                                                   :: Int -> Int -> Int -> Int
greatestPrime num curPrime greatest | (curPrime > num)          = greatest
greatestPrime num curPrime greatest | (mod num curPrime) > 0    = greatestPrime num (curPrime+1) greatest 
greatestPrime num curPrime greatest | (mod num curPrime) == 0   = greatestPrime (num/curPrime) curPrime greatest 

If you were trying to get the highest prime in 10, for example, you would call this with "greatestPrime 10 2 1", so that you would start searching at 2, and your current greatest prime number would be 1.

I would appreciate any help with this - either by helping with type aliasing, general code implementation, or even syntax/ code blocking. I'm new to haskell, so there may be a way of writing this that makes more sense; however, I'm not looking for full algorithm rewrites like a sieve. Thanks for your time.

like image 967
Marshall Conover Avatar asked Dec 22 '22 01:12

Marshall Conover


1 Answers

The / operator has type (/) :: Fractional a => a -> a -> a, which means that it only works on Fractional types like Float, Double and Rational, and not integers.

Use div :: Integral a => a -> a -> a for integer division.

> 10 `div` 2
5
> 7 `div` 2
3

There's also quot, which rounds towards zero instead of negative infinity:

> (-7) `div` 2
-4
> (-7) `quot` 2
-3
like image 192
hammar Avatar answered Jan 19 '23 01:01

hammar