Я недавно изучал Haskell и разговаривал с другом, который работает через SICP.Нам было любопытно сравнить Common Lisp и Scheme, и поэтому я решил в качестве упражнения попытаться перевести упражнение 1.29 в Haskell.
В этом упражнении используется функция сигма, которая представляет математическую функцию суммирования сигма.Эта функция принимает функцию f, применяемую к каждому члену, нижнюю границу, функцию, применяемую к каждому члену, чтобы получить следующий член, и верхнюю границу.Он возвращает сумму f, примененную к каждому члену.
simpsonIntegral должен использовать правило Симпсона для аппроксимации интеграла функции f в диапазоне [a, b] с использованием «точности» n.У меня проблемы с тем, чтобы заставить эту функцию работать, потому что, кажется, есть что-то, чего я не понимаю в задействованных типах.
Этот код будет компилироваться с версией 6.12.1 ghc, но simpsonIntegral получит контекст типа (Integral a, Fractional a), который не имеет никакого смысла, и функция взрывается, как только вы ее вызываете,В какой-то момент у меня это сработало, но то, что я сделал, было настолько очевидно хаком, что я хотел спросить здесь, как это будет обрабатываться идиоматически.
Как идиоматически обрабатывать Integral -> Fractional / Real преобразование, необходимое в h?Я прочитал несколько вещей, но ничто не казалось очевидным и чистым.
sigma :: (Ord a, Num b) => (a -> b) -> a -> (a -> a) -> a -> b
sigma f a next b = iter a 0
where
iter current acc | current > b = acc
| otherwise = iter (next current) (acc + f current)
simpsonIntegral f a b n = 1.0 * (h / 3) * (sigma simTerm 0 (1+) n)
where
h = (b - a) / n
simTerm k = (yk k) * term
where
yk k = f (a + h * k)
term =
case k of
0 -> 1
1 -> 1
otherwise -> if odd k then 4 else 2