交换第一个和最后一个元素haskell

时间:2013-03-17 23:24:44

标签: list haskell

我试图在haskell中交换列表的第一个和最后一个元素。我尝试过模式matchnig,表达式,函数等。这是我的最后一次尝试:

cambio xs = [ cabeza++([x]++cola)|x<-xs, cabeza <- init x, cola <- last x, drop 1 x, drop 0 ([init x])]

我的编译器抛出下一个错误:

Couldn't match expected type `Bool' with actual type `[a0]'
    In the return type of a call of `drop'
    In the expression: drop 1 x
    In a stmt of a list comprehension: drop 1 x

任何人都可以帮助我吗?我已经试着这样做了2天

3 个答案:

答案 0 :(得分:4)

以下是一些提示:

  1. 你无法用列表理解来解决这个问题。
  2. 识别基本(普通)案例 - 空列表和一个元素列表。编写涵盖这些案例的方程式。
  3. 在所有其他情况下,输入列表的长度将是> = 2.您想要的列表是

    [z] ++ xs ++ [a]

  4. 其中z是最后一个元素,输入列表的第一个元素,xs是输入的中间部分。

    现在告诉我(或你自己),如果输入字符串的长度为k,xs会有多长?

    1. 编写涵盖具有多个元素的列表大小写的等式。您可以使用head,last,length,drop或take等功能。

答案 1 :(得分:2)

我认为列表不是执行此操作的最佳数据结构,但在此处:

swap list = last list : (init . tail $ list) ++ [head list]

这将需要遍历列表,并且在长列表中会很慢。这是链接列表的本质。


更新了问题提供者的基本案例:

swap [] = [] 
swap [a] = [a] 
swap list = last list : (init . tail $ list) ++ [head list] 

答案 2 :(得分:2)

这是一件相当简单的事情,尤其是标准列表函数:

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 <- xscabeza <- init xcola <- last x。第一个意味着xs中的每个元素都将用于定义新列表的元素,每个元素将被命名为x。其他两个没有任何意义,因为initlast[a] -> a类型,但是在箭头的右侧,因此必须是列表,{{1} }必须是列表的元素,因为它位于箭头的左侧,所以为了使其均匀编译,xs必须是x类型,我确信这不是你想要的。

您使用的谓词是[[[a]]]drop 1 x。我有点理解你试图用第一个做什么,删除列表的第一个元素,但这不起作用,因为drop 0 [init x]只是列表的一个元素,而不是列表本身。在第二个中,x表示“从以下列表的开头删除零元素”,这绝对不会做任何事情。在任何一种情况下,在谓词中放置类似的东西都行不通,因为谓词需要是一个布尔值,这就是你得到编译器错误的原因。这是一个例子:

drop 0

此函数采用数字列表,删除所有负数,并返回结果。谓词是pos xs = [ x | x <- xs, x >= 0 ] ,它是一个布尔表达式。如果表达式的计算结果为false,则正在评估的元素将从结果列表中过滤掉。

您使用的元素定义是x >= 0。这意味着“结果列表中的每个元素本身都是一个列表,由列表cabeza ++ [x] ++ cola中的所有元素组成,后跟包含cabeza的单个元素,后跟列表中的所有元素{{ 1}}“,这似乎与你的目标相反。请记住,管道字符前面的部分定义了一个元素,而不是列表本身。另请注意,在变量周围放置方括号会创建一个包含该变量的新列表,并且只包含该变量。如果你说x,这意味着y包含单个元素x,并且没有说明x是否是列表。

我希望这有助于澄清一些事情。