的类型签名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
不能同时是 a和Int
aFloat
(as' x (acc-1))
不能同时是 an[a]
和 a Float
---这是第二条错误消息试图告诉你的
最终,您正在尝试使用take
不是列表的东西。我不确定您要做什么。
你可能想要签名
as' :: Float -> Int -> [Float]
那应该(我没有测试过)修复了上面的类型错误,但仍然留下了一个更基本的问题:每当你计算列表的第n个元素时,你都会重新计算列表的 *n-1* 个元素两次(等等,回到列表的开头:重新计算的指数增长),即使这个元素可能已经被计算过了。没有共享正在进行。
例如考虑
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