【问题标题】:What's wrong with my guard-based haskell code for halving a list?我基于守卫的 haskell 代码将列表减半有什么问题?
【发布时间】:2022-01-21 18:10:14
【问题描述】:

代码如下:

    listhalve :: [a] -> ([a],[a])
listhalve (x:xs)
    | length [x] == length xs = ([x],xs)
    | length [x] <  length xs = listhalve ([x] ++ head xs : tail xs)
    | length [x] > length xs = ([x],xs)

当我运行或编译它时没有错误消息,它只是在非对列表的情况下永远运行。

我知道编写这个有效的函数的不同方法。我只想知道这段代码有什么问题特别是

在把你的 cmets 放在心上后,我在这里想出了这个代码:

listhalve :: [a] -> ([a],[a])
listhalve xs = listhalve' [] xs
    where
        listhalve' :: [a] -> [a] -> ([a],[a])
        listhalve' x y
            | length x == length y = (x, y)
            | length x <  length y = listhalve' (x ++ (head y)) (tail y)
            | length x >  length y = (x, y)

这给了我一个错误的阅读:

test.hs:7:56: error:
    * Occurs check: cannot construct the infinite type: a1 ~ [a1]
    * In the second argument of `(++)', namely `(head y)'
      In the first argument of listhalve', namely `(x ++ (head y))'
      In the expression: listhalve' (x ++ (head y)) (tail y)
    * Relevant bindings include
        y :: [a1] (bound at test.hs:5:22)
        x :: [a1] (bound at test.hs:5:20)
        listhalve' :: [a1] -> [a1] -> ([a1], [a1]) (bound at test.hs:5:9)
  |
7 |             | length x <  length y = listhalve' (x ++ (head y)) (tail y)
  |          

这段代码有什么问题?

【问题讨论】:

  • length [x]1 的一种混淆写法。
  • listhalve ([x] ++ head xs : tail xs) 基本上只是listhalve (x:xs)
  • 另外,您的模式匹配并不详尽。您不妨添加listhalve [] = ([], [])
  • @Chris 真的,我认为它会将 x 的长度增加一,并将 xs 的长度减少一,直到它们相等或 x 比 xs 长。
  • x 始终是列表的单个元素,而不是子列表。您似乎认为递归调用是在[[x], xs] 之类的东西上进行的,它不会进行类型检查。您需要从一开始就对列表元组进行操作。考虑使用像go :: [a] -&gt; [a] -&gt; ([a], [a]) 这样的递归帮助器,其中listhalve xs = go [] xs 每次调用go 都应该将一个元素从第二个参数“转移”到第一个参数,直到两个参数的长度足够接近。

标签: list haskell


【解决方案1】:

考虑listhalve ([x] ++ head xs : tail xs)listhalve ([x] ++ xs) 相同,listhalve (x:xs) 与您输入的相同,因此会产生无限递归。

【讨论】:

  • 谢谢。由于某种原因,我认为 listhalve (x:xs) 是两个变量的函数。稍后我将编写一个类似的函数,使用两个参数。
  • 一个在 GHCi 中玩耍的有趣的小单线:halve lst = foldl (\(a1, a2) _ -&gt; let d = length a1 - length a2 in if d &lt;= 1 &amp;&amp; d &gt;= -1 then (a1, a2) else (a1 ++ [head a2], tail a2)) ([], lst) lst。它不是特别有效,但也许你可以从中得到一些东西。
【解决方案2】:

当您将head y 指定为列表时,错误已修复,第二个函数有效,即[head y]。完整的、更正后的函数如下所示:

listhalve :: [a] -> ([a],[a])
listhalve xs = listhalve' [] xs
    where
        listhalve' :: [a] -> [a] -> ([a],[a])
        listhalve' x y
            | length x == length y = (x, y)
            | length x <  length y = listhalve' (x ++ [head y]) (tail y)
            | length x >  length y = (x, y)

【讨论】:

    猜你喜欢
    • 2021-12-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-27
    • 2011-07-05
    • 1970-01-01
    • 2011-07-28
    相关资源
    最近更新 更多