Подтвердить что ты не робот

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

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

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

Спасибо, что прочитали.

4b9b3361

Ответ 1

Используйте 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]

Ответ 2

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

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

halfEvens = map halfIfEven