I want to learn using the ST-Monad. Therefore I want to rewrite a bit of code computing for every integer – up to a limit – the list of all its proper divisors. The result should be an array and the entry of index 'n' should be the list of it's proper divisors.
It is done by computing for each Integer 'n' a list 'l' of its multiples and adding for each multiple 'm' out of 'l' at the index 'm' it's divisor 'n' to the list.
Here's the code I want to modify:
properDivisorsOf' :: forall a. (Integral a, Ix a) => a -> Array a [a]
properDivisorsOf' limit =
let generate :: (Integral a, Ix a) => a -> Array a [a] -> Array a [a]
generate n acc
| n > (limit `div` 2) = acc
| otherwise =
let acc' = acc // [(i, n : (acc ! i)) | i <- [2*n, 3*n .. limit]]
in generate (n + 1) acc'
in generate 1 (array (1, limit) [(i, [])| i <- [1..limit]])
And that's the way how I try it:
properDivisorsOf :: forall a. (Integral a, Ix a) => a -> Array a [a]
properDivisorsOf limit =
let result :: ST s (STArray s a [a])
result = newArray (1, limit) [] -- In the beginning for every number: no divisors known (empty list)
update (index, divisor) = do
l <- readArray result index -- extracting list of divisors of number 'index'
let u = divisor : l
writeArray result index u -- and adding 'divisor' to the list
content :: [(a, a)]
content = do
n <- [1 .. (limit `div` 2)]
multiple <- [2*n, 3*n .. limit]
return (multiple, n)
doUpdate = map update content -- update result for all multiples (in content)
in runSTArray result
Unfortunatley it is not compiling and the error message doesn't say anything to me. I have two questions:
- Why doesn't it compile? How can I extract the entry correctly?
- How would an experienced Haskell-Programm solve this problem under the restriction that he has to work with the ST-Monad (for efficiency purposes)
EDIT: Compiler message
Couldn't match expected type `[t0]'
with actual type `STArray i0 a [a]'
In the second argument of `(:)', namely `l'
In the expression: divisor : l
In an equation for `u': u = divisor : l
Failed, modules loaded: none.