【发布时间】: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] -> [a] -> ([a], [a])这样的递归帮助器,其中listhalve xs = go [] xs每次调用go都应该将一个元素从第二个参数“转移”到第一个参数,直到两个参数的长度足够接近。