I\'m trying to carry out the following computation: sum of the squares of integers in the range x:y where (x <= y).
I\'m not sure how to put a constraint to ensur
The obvious and slow approach is to actually sum those squares:
sumOfSquaresSlow :: Integral a => a -> a -> a
sumOfSquaresSlow lo hi
| lo > hi = error "sumOfSquaresSlow: lo > hi"
| otherwise = sum $ map (^2) [lo..hi]
The time complexity of this approach is linear in max(y-x,0); it will take a while if your range of integers is large; see the benchmark at the bottom of my answer.
However, because there is a formula for the sum of the squares of the first n (positive) integers, you don't actually have to sum those squares one by one.
To issue an error message to the user in case x is greater that y (as specified in your comment), you can simply use the error function, here.
(Edit: thanks to Chris Drost for pointing out that I was overcomplicating things)
sumOfSquaresFast :: Integral a => a -> a -> a
sumOfSquaresFast lo hi
| lo > hi = error "sumOfSquaresFast: lo > hi"
| otherwise = ssq hi - ssq (lo - 1)
where
ssq x = div (((2 * x + 3) * x + 1) * x) 6
Using this formula instead reduces the complexity to something close to constant time.
λ> :set +s
λ> sumOfSquaresSlow (10^3) (10^7)
333333383333002166500
(17.19 secs, 11563005552 bytes)
λ> sumOfSquaresFast (10^3) (10^7)
333333383333002166500
(0.01 secs, 3106112 bytes)