【问题标题】:Haskell, pulling both lists from a tuple of listsHaskell,从列表元组中提取两个列表
【发布时间】:2014-10-06 05:26:55
【问题描述】:

我正在使用 2 个辅助函数进行“合并排序”。第一个辅助函数将列表拆分为列表元组,将奇数和偶数索引放在单独的列表中。

Example: [1,2,3,4,5,6]
Returns: ([1,3,5],[2,4,6])

第二个辅助函数假定列表已排序并合并它们。

我将使用这两个函数来实现一个未排序列表的合并排序。

我有这个非常低效的片段,它基本上拆分 (length - 1) * 2 次并合并列表 (length - 1) 次。

   sort length (z:zs)
        | length == 0 = (z:zs)
        | otherwise   = sort (length - 1) (merge (fst (split(z:zs))) (snd (split(z:zs)))

我调用 split 两次以获得与第一次拆分相同的信息,但我递归的不够远(每个列表只是一个单例,然后将它们全部合并)。

如何递归到单例情况并同时提取元组的两个元素?

提前感谢您提供的任何帮助。

【问题讨论】:

  • 看看wherelet 结构。使用类似where (first, second) = split ... 的东西。此外,您可以使用 all@(x:xs) 这样的构造将变量绑定到整个列表。
  • length参数有什么作用?
  • 如果您有不同的问题,请将其作为新问题发布,不要只是将其添加到现有问题中。
  • 哦!谢谢,这是有道理的。对不起,我是堆栈溢出的新手。我会记住这一点的。
  • 你真的需要你的长度参数或者你可以通过其他方式检测单例情况吗?

标签: list haskell tuples


【解决方案1】:

您可以使用uncurrymerge 转换为非柯里化函数并将split(z:zs) 作为参数传递:

sort (length - 1) $ uncurry merge $ split (z:zs)

uncurry 函数将a -> b -> c 类型的函数转换为(a, b) -> c 类型的函数。在您的情况下,merge 的类型为 [a] -> [a] -> [a],而 uncurry merge 的类型为 ([a], [a]) -> [a]([a], [a]) 的返回类型为 split

或者,您可以简单地使用letwhere 子句来引用split 的结果:

let (left, right) = split (z:zs)
in sort (length - 1) $ merge left right

这是一个改进版:

let res = split (z:zs)
in sort (length - 1) $ merge (fst res) (snd res)

附带说明您的sort 函数不正确。你的定义是这样的:

sort length (z:zs) = ...

但是这仅匹配 非空 列表。当它永远不会发生时,考虑length == 0 的情况也是毫无用处的。

你对sort的定义也应该考虑空壳:

sort _ [] = []
sort length (z:zs) = ...

【讨论】:

  • 我希望有一天这一切对我来说都有意义!现在,谢谢你!
  • uncurry 应用于元数大于 2 的函数时的行为是什么?
  • @Mark 对此的标准回复是,在 Haskell 中,每个函数的数量都恰好为 1(一)。所以c in a->b->c ===> (a,b)->c 也可以是d->e->f->... 一样。
  • @WillNess,是的,我知道,但我还是 Haskell 的新手,我已经对其进行了测试:uncurry f $ (1, 2) 3 - 它有效 :-)
  • @Mark 问一下是完全可以的。 :)
猜你喜欢
  • 2012-02-29
  • 1970-01-01
  • 1970-01-01
  • 2013-03-25
  • 1970-01-01
  • 2011-08-25
  • 2011-11-16
  • 1970-01-01
  • 2020-01-09
相关资源
最近更新 更多