Проблема заключается в том, что
length :: [a] -> Int
но
(/) :: (Fractional a) => a -> a -> a
Итак, когда вы говорите whatever/length xs
, это не тип, потому что Int не является фракционный тип номера! Это то, что пытается сказать вам ошибка «Нет экземпляра для ...». Это определение будет работать:
GHCi> let avg xs = sum xs/fromIntegral (length xs)
Здесь мы используем fromIntegral :: (Integral a, Num b) => a -> b
преобразовать Int мы получаем от length
в дробное число. Обратите внимание, что полученная функция будет работать только в списках Дробных чисел из-за этого (но, например, avg [1,2,3]
все равно будет работать нормально).
Чтобы объяснить ошибки вы получаете, когда делать это «на части», это потому, что в let a = sum [1,2]
, элементы в списке являются Целые, поэтому их сумма является Integer, но в let b = length [1,2]
, результирующая длина является Int, согласно типу от length
Я показал выше. Итак, когда вы делаете a/b
, это не удается, даже если он даже понимает, что Int и Integer не являются экземплярами Fractional - поскольку (/)
принимает два аргумента одного типа, он не может работать.
И да, Integer и Int отличаются друг от друга - Int является интегральным типом с фиксированной точностью, обычно размером с числовым словом, например long
в C, тогда как Integer представляет собой произвольный прецизионный бигнам, способный хранить любое целое число; или, по крайней мере, любое целое число, которое будет соответствовать в оперативной памяти :)
Другим возможным подходом было бы определить, как avg xs
sum xs/genericLength xs
, используя Data.List.genericLength
, который работает с любым числовым типом, а не только Ints:
genericLength :: (Num b) => [a] -> b
Для этого вам нужно будет import Data.List
в GHCi. Еще один возможный подход (но один из которых приводит к другой функции вообще) заключается в использовании целочисленного деления: let avg xs = sum xs `div` length xs
(примечание: a `div` b
- это всего лишь div a b
, этот синтаксический сахар работает для каждой функции).
Требуется больше 'fromIntegral'. =) –