Моя avg
сигнатура функции не должна иметь ничего общего с причудами оператора деления
Почему это? Если вы хотите вычислить среднее значение для целого числа целых чисел, вам придется в какой-то момент разделить их, поэтому вам придется преобразовать их из целых чисел в поддерживаемый по вашему выбору тип поддержки. При внимательном рассмотрении класса Num
(:i Num
в ghci) обнаруживается одна проблема с типом avg
: Num
не имеет достаточно методов - в основном достаточно для сложения, умножения и вычитания. Нет никакой гарантии, что число, которое я даю avg
, можно вообще преобразовать в Double
.
Если вы введете нетипизированную функцию для вычисления среднего, Haskell ответит самым общим из возможных типов:
Prelude List> :type \x -> sum x / genericLength x
\x -> sum x / genericLength x :: (Fractional a) => [a] -> a
Так что это правильный тип avg
.
Вы можете заметить, что avg [1,2,3 :: Integer]
выдает ошибку типа. Вы можете обойти это, передав аргумент сначала toRational
или fromIntegral
, которые используют экземпляры Real
и Integral
для Integer
соответственно.
Относительно выражения sum [1,2,3] / len [1,2,3]
: Это правда, что буквенное число, такое как 1
, имеет тип Num a => a
, что вызывает fromInteger
для любого типа, которым оно окажется, но выражение, подобное 1/2
, имеет более конкретный тип Fractional a => a
, который вы можете увидеть, если спросите тип этого выражения вместо его распечатки.
Что-то, что могло бы быть полезным, это :set -Wall
в ghci, который включает много предупреждений всякий раз, когда для вас выбран тип по умолчанию, давая понять, что наиболее общий тип может больше не быть правильным.