Отдел в Хаскеле - PullRequest
       17

Отдел в Хаскеле

26 голосов
/ 10 сентября 2011

Я делаю в Haskell функцию, которая делит пополам только четные числа в списке, и у меня возникла проблема.Когда я запускаю компилятор, он жалуется, что вы не можете выполнить деление типа int и что мне нужно объявление типа дробного типа int.Я попытался изменить объявление типа на float, но это просто вызвало еще одну ошибку.Я включил код функции ниже и надеялся на любую форму помощи.

halfEvens :: [Int] -> [Int]
halfEvens [] = []
halfEvens (x:xs) | odd x = halfEvens xs
                 | otherwise = x/2:halfEvens xs

Спасибо за чтение.

Ответы [ 2 ]

39 голосов
/ 10 сентября 2011

Использовать div, который выполняет целочисленное деление:

halfEvens :: [Int] -> [Int]
halfEvens [] = []
halfEvens (x:xs) | odd x = halfEvens xs
                 | otherwise = x `div` 2 : halfEvens xs

Функция (/) требует аргументы, тип которых находится в классе Fractional, и выполняет стандартное деление. Функция div требует аргументов, тип которых находится в классе Integral, и выполняет целочисленное деление.

Точнее, div и mod округляются до отрицательной бесконечности. Их кузены, quot и rem, ведут себя как целочисленное деление в C и округляются до нуля. div и mod обычно правильны при выполнении модульной арифметики (например, при расчете дня недели с учетом даты), тогда как quot и rem немного быстрее (я думаю).

Немного поиграть в GHCi:

> :t div
div :: Integral a => a -> a -> a
> :t (/)
(/) :: Fractional a => a -> a -> a
> 3 / 5
0.6
> 3 `div` 5
0
> (-3) `div` 5
-1
> (-3) `quot` 5
0
> [x `mod` 3 | x <- [-10..10]]
[2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1]
> [x `rem` 3 | x <- [-10..10]]
[-1,0,-2,-1,0,-2,-1,0,-2,-1,0,1,2,0,1,2,0,1,2,0,1]
0 голосов
/ 08 сентября 2015

Я должен добавить, что использование map упростит код.

HalfIfEven n
  | even n = n `div` 2
  | otherwise = n

halfEvens = map halfIfEven
...