这是一件相当简单的事情,尤其是使用标准列表函数:
swapfl [] = []
swapfl [x] = [x]
swapfl (x:xs) = (last xs : init xs) ++ [x]
或者没有它们(尽管这不太可读,通常不做,也不推荐):
swapfl' [] = []
swapfl' [x] = [x]
swapfl' (x:xs) = let (f, g) = sw x xs in f:g
where sw k [y] = (y, [k])
sw k (y:ys) = let (n, m) = sw k ys in (n, y:m)
或许多其他方式之一。
我希望这会有所帮助......我知道我没有做太多解释,但坦率地说,就这个功能而言,很难确切地说出你遇到了什么问题,因为你似乎也完全误解了列表理解。我认为如果我解释这些可能是最有益的?
为什么这不能通过列表理解来解决?我强硬他们就像函数但有不同的形式
并不真地。列表推导式对于轻松定义列表很有用,并且它们与数学中的集合构建符号非常密切相关。这对于这个特定的应用程序没有用处,因为虽然它们非常擅长修改列表的元素,但推导式并不擅长重新排序列表。
在理解中,您包含三个部分:列表中元素的定义、一个或多个输入列表以及零个或多个谓词:
[ definition | x <- input1, y <- input2, predicate1, predicate2 ]
该定义描述了我们正在制作的列表的单个元素,根据输入中的箭头指向的变量(在本例中为 x 和 y)。每个输入在箭头右侧都有一个列表,在左侧有一个变量。我们正在制作的列表中的每个元素都是通过将输入列表中的每个元素组合提取到这些变量中来构建的,并使用这些值评估定义部分。例如:
[ x + y | x <- [1, 3], y <- [2, 4] ]
这会产生:
[1 + 2, 1 + 4, 3 + 2, 3 + 4] == [3, 5, 5, 7]
此外,您可以包含谓词,类似于过滤器。每个谓词都是根据输入元素定义的布尔表达式,并且只要有新的列表元素,就会对每个谓词进行评估。如果任何谓词结果为假,则这些元素不会放在我们正在制作的列表中。
让我们看看你的代码:
cambio xs = [ cabeza++([x]++cola) | x<-xs, cabeza <- init x, cola <- last x,
drop 1 x, drop 0 ([init x])]
这种理解的输入是x <- xs
、cabeza <- init x
和cola <- last x
。第一个意味着其中的每个元素xs
都将用于为新列表定义元素,并且每个元素都将被命名x
。另外两个没有任何意义,因为init
andlast
是 type [a] -> a
,但是在箭头的右侧,所以必须是列表,并且x
必须是列表的元素,因为它在箭头的左侧,所以在为了使它甚至可以编译, xs 必须是 type [[[a]]]
,我敢肯定这不是您想要的。
您使用的谓词是drop 1 x
and drop 0 [init x]
。我有点理解你试图用第一个做什么,删除列表的第一个元素,但这不起作用,因为x
它只是列表的一个元素,而不是列表本身。在第二个中,drop 0
表示“从以下列表的开头删除零个元素”,这绝对不会做任何事情。在任何一种情况下,将类似的东西放在谓词中都行不通,因为谓词需要是一个布尔值,这就是你得到编译器错误的原因。这是一个例子:
pos xs = [ x | x <- xs, x >= 0 ]
这个函数接受一个数字列表,删除所有负数,并返回结果。谓词是x >= 0
,它是一个布尔表达式。如果表达式的计算结果为 false,则正在计算的元素会从结果列表中过滤掉。
您使用的元素定义是cabeza ++ [x] ++ cola
. 这意味着“结果列表中的每个元素本身就是一个列表,由列表中的所有元素组成cabeza
,后跟一个包含 的元素x
,然后是列表中的所有元素cola
”,这似乎与您的意图相反为了。请记住,管道字符之前的部分定义了单个元素,而不是列表本身。另外,请注意,将方括号括在变量周围会创建一个包含该变量的新列表,并且仅包含该变量。如果你说y = [x]
,这意味着 y 包含单个元素 x,并且没有说明 x 是否是列表。
我希望这有助于澄清一些事情。