Haskell 在特定整数的实例上拆分列表
我正在尝试编写一个函数,将一个特定整数的实例上的列表拆分为几个单独的列表。例如:Haskell 在特定整数的实例上拆分列表,haskell,Haskell,我正在尝试编写一个函数,将一个特定整数的实例上的列表拆分为几个单独的列表。例如: splitlist[3,4,0,6,0,7]0将返回[[3,4]、[6]、[7]] 到目前为止,我已经: splitlist :: [Int] -> Int -> [[Int]] splitlist xs n | length xs == 0 = [] | head xs == n = [head (tail xs)] : splitlist (tail xs) n | otherwis
splitlist[3,4,0,6,0,7]0
将返回[[3,4]、[6]、[7]]
到目前为止,我已经:
splitlist :: [Int] -> Int -> [[Int]]
splitlist xs n
| length xs == 0 = []
| head xs == n = [head (tail xs)] : splitlist (tail xs) n
| otherwise = [head xs : splitlist (tail xs) n]
但是,我在第5行得到了头xs的类型错误:
• Couldn't match type ‘[Int]’ with ‘Int’
Expected type: [Int]
Actual type: [[Int]]
• In the second argument of ‘(:)’, namely ‘splitlist (tail xs) n’
In the expression: head xs : splitlist (tail xs) n
In the expression: [head xs : splitlist (tail xs) n]
|
5 | | otherwise = [head xs : splitlist (tail xs) n]
| ^^^^^^^^^^^^^^^^^^^^^
我做错了什么?
xs
有类型[Int]
,所以头xs
有类型Int
<代码>拆分列表具有类型[Int]->Int->[[Int]]]
,因此拆分列表(尾部xs)n
具有类型[[Int]]
。您试图对这些值调用:
,其类型为a->[a]->[a]
。问题是,没有选择a
就可以解决这个问题:如果你为a
选择Int
,那么它是错误的,因为第二个参数是[[Int]]
而不是[Int]
,如果你为a
选择[Int]
,那么它就错了,那么它就错了,因为第一个参数是Int
,而不是[Int]
我想你是想写[head-xs]:splitlist(tail-xs)n
而不是[head-xs:splitlist(tail-xs)n]
,就像上面那行一样。但是,尽管此类型进行了检查,但仍然不起作用(它会在测试用例上生成[[3]、[4]、[6]、[6]、[7]、[7]
,以及拆分列表[0]0
底部)
要真正修复它,首先让我们重写它,使其看起来更地道:
splitlist :: [Int] -> Int -> [[Int]]
splitlist [] _ = []
splitlist (x:xs) n
| x == n = [head xs] : splitlist xs n
| otherwise = [x] : splitlist xs n
我所做的改变是,我使用模式匹配来代替测试长度
,然后使用头部
和尾部
。现在,逻辑问题变得显而易见:
- 如果列表的最后一个元素是分隔符,则它将降到底部
- 结果始终是一个仅包含单个元素列表的列表
- 对于输入中的每个
,输出中总是有一个Int
Int
我想这是一种练习,所以我不会破坏最后的答案。但是,这应该足以让您再次尝试。作为一般建议,当模式匹配就足够时,使用
长度、头部、尾部
被认为是一种不好的做法。在最坏的情况下,你会得到一个崩溃的程序,就像上面的一个:为什么head(tailxs)
在一个非空列表上会成功?通常,您会得到一个效率低下的程序:length xs==0
扫描整个列表以计算其元素,但没有必要这样做。这是否回答了您的问题?谢谢我之所以尝试使用[head-xs:splitlist(tail-xs)n]
是因为我试图解决您指出的第二个问题,即它始终是一个仅包含单个元素列表的列表。我仍然不知道该怎么做——我试图将x作为列表的第一个元素,然后再次调用该函数,但是我仍然得到类型错误,我不太确定如何避免。我也尝试过使用++,但我认为在模式匹配中不允许这样做。