我想把一个列表分成n个元素的组。例如:
n = 2
[1, 2, 3, 4, 5, 6] ->[[1, 2], [3, 4], [5,6]]
n = 3
[1, 2, 3, 4, 5, 6] -> [[1, 2, 3] [4, 5, 6]]
我尝试实现一个函数,如果n为0或大于列表长度,则返回n;如果n小于列表长度,返回拟合列表。
split :: Int -> [a] -> Either Int [[a]]
split n [a]
|n <= lenght [a] = Right n (take n [a]) : (split n (drop n [a]))
|n == 0 = Left n
|otherwise = Left n
然而,我得到了一个";变量不在范围内";错误我已经试过了,但是我被卡住了。我在数据类型上犯了错误吗?
您在lenght
与length
之间有一个拼写错误,但如果我们更改它,仍然存在错误。
如果我们观察Right n (take n [a])
,我们可以看到Right
和Left
只接受一个参数。
您的模式split n [a]
也只匹配具有单个元素的列表。
让我们把它分解成更小的部分。创建一个拆分列表的函数非常简单。
split' n [] = []
split' n lst = take n lst : (split' n $ drop n lst)
Prelude> split' 3 [1,2,3,4,5,6]
[[1,2,3],[4,5,6]]
现在,将其设为split
的本地,以合并您指定的检查并返回所需的Either
类型,就很简单了。
split :: Int -> [a] -> Either Int [[a]]
split n [] = Left n
split n lst
| n == 0 || n > length lst = Left n
| otherwise = Right lst'
where
split' n [] = []
split' n lst = take n lst : (split' n $ drop n lst)
lst' = split' n lst