Ввод в Haskell: передача числа, которое выглядит дробным, но всегда будет целым числом (псевдоним типа)

В настоящее время я изучаю Haskell с помощью веб-сайта Gentle Introduction to Haskell, и я сделал перерыв на полпути к разделу 4 проверить свои знания. Я пытаюсь реализовать функцию «наибольшего простого числа в составном числе», которую я использовал, когда работал на C, но у меня проблемы с системой набора текста Haskell. Я пытаюсь передать число, которое выглядит как дробное целое, но поскольку я использовал модуль, чтобы проверить, делится ли оно, я знаю, что оно будет оцениваться как целое число. Вот контекст:

C: Я прокомментировал это на случай, если что-то непонятно, но код должен быть довольно простым.

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.
    }

}

Например, если вы ищете самое высокое из 10, вы бы назвали это, сказав «самое высокое (10, 2, 1)» — вы ищете самое высокое простое число из 10, начиная с 2, и текущее самое высокое простое число. в числе равно 1. Он вернется, когда попытается использовать число 5 в качестве делителя во второй раз и увидит, что curDom теперь равен 1.

Проблема в том, что когда я пробую это в Haskell, в четвертой строке моего кода я сталкиваюсь с проблемой передачи числа, деленного на простое число, которое входит в него - это выглядит как дробное целое, но поскольку я уже проверено с модулем, я знаю, что он будет разрешаться в обычный Int. Вот код, с которым я работаю:

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 

Например, если бы вы пытались получить наибольшее простое число из числа 10, вы бы назвали это с помощью «greatestPrime 10 2 1», чтобы начать поиск с 2, и вашим текущим наибольшим простым числом было бы 1.

Я был бы признателен за любую помощь в этом - либо за помощь с псевдонимами типов, либо за общую реализацию кода, либо даже за блокировку синтаксиса/кода. Я новичок в haskell, поэтому может быть способ написать это, который имеет больше смысла; однако я не ищу полного переписывания алгоритма, как сито. Спасибо за ваше время.


person Marshall Conover    schedule 05.03.2012    source источник
comment
О, это мягкое введение в Haskell, которое вы читаете, на самом деле не такое уж мягкое — и к этому моменту оно довольно устарело. Два лучших ресурса для изучения Haskell в наши дни: Learn You a Haskell и Реальный язык Haskell. Я бы тоже читал их в таком порядке: *Learn You a Haskell* более теоретический, но и более мягкий, а Real World Haskell более практичен и немного сложнее (ИМХО).   -  person Luis Casillas    schedule 06.03.2012
comment
@sacundim - Спасибо, Learn You, Haskell, безусловно, немного мягче. Должен сказать, мне нравится темп «Нежного введения», тем не менее, он заставляет меня делать паузы и пытаться осмыслить многие вещи, что заставляет их глубже проникнуть в суть — не говоря уже о том, что я смог загрузить его и прочитать во время полета, что является бонусом. Я сейчас читаю «Узнай тебя», хотя, возможно, когда-нибудь вернусь к «Нежному».   -  person Marshall Conover    schedule 06.03.2012
comment
Дело в том, что мягкое введение начинается с простого, затем в какой-то момент происходит огромный скачок в сложности. Насколько я помню, именно в этот момент начинают говорить о вводе-выводе и монадах...   -  person Luis Casillas    schedule 06.03.2012


Ответы (1)


Оператор / имеет тип (/) :: Fractional a => a -> a -> a, что означает, что он работает только с типами Fractional, такими как Float, Double и Rational, а не с целыми числами.

Используйте div :: Integral a => a -> a -> a для целочисленного деления.

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

Также есть quot, который округляет до нуля вместо отрицательная бесконечность:

> (-7) `div` 2
-4
> (-7) `quot` 2
-3
person hammar    schedule 05.03.2012
comment
Спасибо! Это сработало отлично. Кстати, для чего нужны обратные кавычки? - person Marshall Conover; 06.03.2012
comment
@MarshallConover: они превращают функции в операторы, поэтому 7 `div` 2 совпадает с div 7 2. Точно так же вы можете использовать круглые скобки, чтобы превратить оператор в функцию, поэтому 2 + 3 совпадает с (+) 2 3. - person hammar; 06.03.2012
comment
Обратите внимание, что quot немного быстрее, чем div, потому что это оператор, реализованный непосредственно в процессоре, div должен обрабатывать результаты, потому что он иначе обрабатывает отрицательные результаты. (аналогично rem быстрее, чем mod ) Разница заметна, когда вы используете один из этих операторов в большом цикле. - person Jedai; 07.03.2012