Haskell反转对

时间:2013-02-11 17:08:11

标签: haskell

想知道我是否可以帮助编写这个功能。我正在尝试创建一个函数来反转列表中的每个“对”。

module Invert where
invert :: [(a,b)] -> [(b,a)]
invert [(a,b)] = [(b,a)]

当我输入invert [(3,1) (4,1) (5,1)]时...应该给我[(1,3) (1,4) (1,5) ......但它给了我......


*Invert> [(3,1) (4,1) (5,1)]

<interactive>:2:2:
    The function `(3, 1)' is applied to two arguments,
    but its type `(t0, t1)' has none
    In the expression: (3, 1) (4, 1) (5, 1)
    In the expression: [(3, 1) (4, 1) (5, 1)]
    In an equation for `it': it = [(3, 1) (4, 1) (5, 1)]

3 个答案:

答案 0 :(得分:15)

由于列表是递归数据结构,因此您必须递归处理列表以交换其所有元素,或使用一些更高阶函数为您执行处理。如果你定义

invert [(a,b)] = [(b,a)]

它只会转换单个元素列表,所有其他输入都会失败并显示错误!

尝试考虑输入invert得到:它是一个空列表,或者是一个非空列表。在非空列表的情况下,您可以交换第一个元素并以递归方式转换其余元素。

(如果您不想自己反转invert,请使用

invert = map swap

其中swap来自Data.Tuple。)

答案 1 :(得分:4)

解决此问题的最佳方法:将其拆分为较小的问题,找到解决这些问题的库函数,或编写自己的函数。我总是告诉初学者这是一个优秀的练习,而不仅仅是尝试编写像invert这样的函数,因为你应该学习以下三件事:

  1. 如何将问题分成小的,可重复使用的部分。
  2. 该语言提供的标准库函数。
  3. 如何使用递归来编写像标准库中那样的小型可重用函数。
  4. 在这种情况下,我们可以将问题分解为:

    1. 反转单个元组。
    2. 将函数应用于列表的所有元素,并收集结果列表。
    3. 第二个是列表中的常见map函数,它附带标准库。你可以尝试编写自己的版本;对于初学者来说,这类事总是很好的练习:

      map :: (a -> b) -> [a] -> [b]
      map f []     = ...
      map f (x:xs) = ...
      

      正如彼得指出的那样,第一个是来自swap的{​​{1}}函数。但我们可以轻松编写自己的文章:

      Data.Tuple

      现在,当然:

      swap :: (a, b) -> (b, a)
      swap (a, b) = (b, a)
      

答案 2 :(得分:3)

因此,您希望在(a, b) -> (b, a)类型的列表上映射函数。函数(,)的类型为b -> a -> (b,a)。因此,如果我们翻转它,我们会得到a -> b -> (b, a)。现在,如果我们发现 ,我们会得到(a, b) -> (b, a)

 invert = map (uncurry $ flip (,))

E.g。

 > map (uncurry $ flip (,)) [(1, "a"), (2, "b")]
 [("a",1),("b",2)]

另外,你的模式匹配与你想要的不匹配。定义

invert [(a,b)] = [(b,a)]

“匹配一个包含单个元组的列表”。如果您有一个包含多个元组的列表,则匹配将失败。另外,正如Josh Lee指出的那样,你的列表中的元组之间需要使用逗号。