Я играю с новичком Haskell, и я хотел написать среднюю функцию. Это казалось простейшей вещью в мире, верно?
Неправильно.
Кажется, что система типа Haskell запрещает среднюю работу от общего числового типа - я могу заставить ее работать над списком Integrals или списком Fractionals, но не для обоих.
Я хочу:
average :: (Num a, Fractional b) => [a] -> b
average xs = ...
Но я могу получить:
averageInt :: (Integral a, Fractional b) => [a] -> b
averageInt xs = fromIntegral (sum xs) / fromIntegral (length xs)
или
averageFrac :: (Fractional a) => [a] -> a
averageFrac xs = sum xs / fromIntegral (length xs)
и второй, похоже, работает. Пока я не попытаюсь передать переменную.
*Main> averageFrac [1,2,3]
2.0
*Main> let x = [1,2,3]
*Main> :t x
x :: [Integer]
*Main> averageFrac x
<interactive>:1:0:
No instance for (Fractional Integer)
arising from a use of `averageFrac ' at <interactive>:1:0-8
Possible fix: add an instance declaration for (Fractional Integer)
In the expression: average x
In the definition of `it': it = averageFrac x
По-видимому, Haskell очень разборчив по своим типам. В этом есть смысл. Но не тогда, когда они могут быть [Num]
Я пропустил очевидное применение RealFrac?
Есть ли способ принудить Integrals к Fractionals, который не задыхается, когда он получает вход Fractional?
Есть ли способ использовать Either
и Either
, чтобы сделать какую-то полиморфную среднюю функцию, которая будет работать на любом виде числового массива?
Система типа Haskell прямо запрещает эту функцию из существующих?
Обучение Haskell похоже на изучение Исчисления. Это действительно сложно и основано на горах теории, и иногда проблема настолько разумно сложна, что я даже не знаю достаточно, чтобы правильно сформулировать вопрос, поэтому любое понимание будет тепло принято.
(Кроме того, сноска: это основано на проблеме домашних заданий. Все согласны с тем, что averageFrac, выше, получает полные баллы, но у меня есть скрытое подозрение, что есть способ заставить его работать как с массивами Integral AND Fractional)