STモナドを使って学びたい。したがって、すべての整数について計算するコードを少し書き直して、限界まで、すべての適切な約数のリストを作成したいと思います。結果は配列である必要があり、インデックス 'n' のエントリは適切な除数のリストである必要があります。
これは、整数 'n' ごとにその倍数のリスト 'l' を計算し、インデックス 'm' で 'l' から倍数 'm' ごとにリストに除数 'n' を追加することによって行われます。
変更したいコードは次のとおりです。
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]])
そして、それが私がそれを試す方法です:
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)
runSTArray の結果
残念ながら、それはコンパイルされておらず、エラーメッセージは私に何も言いません。2 つの質問があります。
- なぜコンパイルされないのですか?エントリを正しく抽出するにはどうすればよいですか?
- 経験豊富な Haskell-Programm は、ST-Monad を使用しなければならないという制限の下で、この問題をどのように解決するでしょうか (効率化のため)。
編集: コンパイラ メッセージ
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
失敗しました。モジュールがロードされました: なし。