Haskell: I seem to not be able to link anything to my accumulator in following recursive function – can anyone explain where I am wrong here?

huangapple go评论77阅读模式
英文:

Haskell: I seem to not be able to link anything to my accumulator in following recursive function - can anyone explain where I am wrong here?

问题

我的解决方案:

start list = start' list []
    where
        start' (x:[]) acc = acc
        start' (x:xs) acc = start' xs (acc ++ [x])

尝试编译时,GHC 似乎会因为第4行中的最后一个表达式 '(acc ++ [x])' 而抛出错误。有人能解释为什么吗?我不太关心这是否是解决问题的最有效方式 - 我只想知道我错在哪里。谢谢。

英文:

Task:
"Define a function 'start' that returns all the elements of a given list but the last one"

My solution:

start list = start' list []
    where
        start' (x:[]) acc = acc
        start' (x:xs) acc = start' xs (acc:x)

When trying to compile, ghc seems to throw an error because of the very last expression in line 4 at '(acc:x)'.
Can somebody explain, why that is?
I don't really care if this is the most efficient way of solving this problem - I just want to get where I am wrong.

Thanks a lot.

答案1

得分: 3

(acc:x) 没有太多意义:acc 是一个列表,x 是一个元素。(:) :: a -> [a] -> [a] 接受一个项目和一个列表,并构造一个列表,其中项目是第一个项目,给定列表是结果中的剩余项目的列表。

你可以在右边附加元素:

start list = start' list []
  where
    start' (x : []) acc = acc
    start' (x : xs) acc = start' xs (acc ++ [x])

你的 start 在这里基本上做了 init :: [a] -> [a] 做的事情,只是你的 start 版本还可以处理空列表。

然而,使用累加器是不必要的,只会增加计算工作和内存使用。你可以使用以下方式工作:

start :: [a] -> [a]
start [] = []
start (x : xs) = go xs x
  where
    go [] _ = []
    go (x : xs) y = y : go xs x

或者更短:

start :: [a] -> [a]
start [] = []
start (x : xs) = go xs x
  where
    go [] = const []
    go (x : xs) = (: go xs x)

这允许处理无限列表,其中 start 永远不会停止,但只需要有限的内存。

英文:

(acc:x) makes not much sense: acc is a list, x is an element. (:) :: a -> [a] -> [a] takes an item and a list, and construct a list where the item is the first item and the given list is the list of remaining items in the result.

You can append at the right end with:

<pre><code>start list = start' list []
where
start' (x : []) acc = acc
start' (x : xs) acc = start' xs (acc ++ [x])</code></pre>

Your start here basically does what init :: [a] -&gt; [a] does, except that your start version also works for empty lists.

Using an accumulator however is not necessary and will only increase the computational effort and memory usage. You can work with:

<pre><code>start :: [a] -&gt; [a]
start [] = []
start (x : xs) = go xs x
where
go [] _ = []
go (x : xs) y = <b>y :</b> go xs x</code></pre>

or shorter:
<pre><code>start :: [a] -&gt; [a]
start [] = []
start (x : xs) = go xs x
where
go [] = <b>const []</b>
go (x : xs) = <b>(:</b> go xs x<b>)</b></code></pre>

This allows to work with infinite lists as well, where the start will never stop, but only needs a limited amount of memory.

huangapple
  • 本文由 发表于 2023年6月26日 05:14:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76552439.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定