причина проблемы
Тип функции sqrt
:
sqrt :: (Floating a) => a -> a
Вы можете проверить это, набрав :t sqrt
в ghci.
Int
не является экземпляром Floating
, поэтому вы видите вторую ошибку.
Причина первой ошибки та же; проверка :t floor
показывает, что тип:
floor :: (RealFrac a, Integral b) => a -> b
Функция ожидает экземпляр RealFrac
, и вы предоставляете Int
.
Ввод :info RealFrac
или :info Floating
показывает, что ни у одного из них нет экземпляра для Int
, поэтому в тексте ошибки указано
Нет экземпляра для ... Int
Решение
Решение этой проблемы - убедиться в правильности типов; они должны быть членами соответствующих классов типов.
Простой способ сделать это - использовать функцию fromIntegral
, которая, как показывает :t
, имеет тип:
fromIntegral :: (Integral a, Num b) => a -> b
Использование fromIntegral
необходимо, поскольку входящий тип - Int
, но функции floor
и sqrt
работают с типами RealFrac
и Floating
соответственно.
Это разрешено, потому что, как видно из сигнатуры типа, fromIntegral
возвращает экземпляр Num
, который включает в себя оба типа: RealFrac
и Floating
. Вы можете убедиться в этом, набрав :info Num
и :info Float
в ghci и просмотрев вывод.
Внесение изменений в вашу программу будет иметь следующий результат, который будет работать так, как вы хотите:
factors :: Int -> [Int]
factors n = [x | x <- [2..s], n `mod` x == 0]
where s = floor (sqrt $ fromIntegral n)
Дальнейшее чтение
Два хороших ресурса для точного понимания происходящего - разделы учебника по Haskell по Классам типов и Числа .