の型シグネチャtake
は
take :: Int -> [a] -> [a]
使用方法は次のとおりですtake
。
take (acc-1) (as' x (acc-1))
したがって、次のように結論付けることができます
(acc-1) :: Int -- first parameter to `take`
acc :: Int -- therefore
(as' x (acc-1)) :: [a] -- second parameter to `take`, we don't know what `a` is
しかし、あなたのコードは言う
as' :: Float -> Float -> Float
as' x acc = ...
そこから私たちは推測します
x :: Float -- first parameter to `as'`
acc :: Float -- second parameter to `as'`
(as' x (acc-1)) :: Float -- result of `as'`
これは、いくつかの矛盾につながります。
acc
Int
と をFloat
同時に指定することはできません
(as' x (acc-1))
[a]
と を同時に指定することはできませんFloat
--- これは、2 番目のエラー メッセージが伝えようとしている内容です。
最終的にtake
、リストではないもので使用しようとしています。あなたが何をしようとしているのかわからない。
あなたはおそらく署名を持っているつもりでした
as' :: Float -> Int -> [Float]
これで (私はテストしていませんが) 上記の型エラーは修正されるはずですが、さらに根本的な問題が残っています: リストのn番目の要素を計算するたびに、リストの *n-1* 番目の要素を新たに2 回計算します。 (など、リストの先頭に戻ります: 再計算の指数関数的成長)、おそらくこの要素は既に計算されていますが。共有は行われていません。
例えば考慮
as' x acc = ( prev + (acc / prev) ) / 2 : as' x (acc+1)
where prev = last(take (acc-1) (as' x (acc-1)))
これはまだ非効率的です: リストの以前の要素を再計算します。しかし今では、次の要素を計算するときに、以前のすべての要素を一度だけ再計算します。
last(take (acc-1) (as' x (acc-1)))
( に簡略化できることを指摘しないのも私の怠慢です(as' x (acc-1)) !! (acc-2)
。)
各要素が前の要素のみに依存する無限リストを生成する通常の方法は、 を使用することiterate
です。
複雑なのは、各要素がアキュムレータと前の要素に依存していることです。アキュムレータをリストの各要素に組み込むことで、これを回避します。完了したら、アキュムレータを破棄して、最終的な無限リストを生成します。
approxRoots :: Float -> [Float]
approxRoots x = map fst $ iterate next (x, 1)
-- I don't know what your initial approximation should be
-- I've put `x` but that's probably wrong
where next (prev, acc) = (prev + acc / prev, acc + 1)
-- First element of each pair is the approximation,
-- second element of each pair is the "accumulator" (actually an index)
-- I've probably transcribed your formula wrongly