2014-10-06 55 views
1

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

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

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

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

我有这个非常低效率的片断,基本上分割(长度 - 1)* 2次并合并列表(长度 - 1)次。

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

我打电话分裂两次,得到这是第一个分割做了同样的信息,我不会递归远远不够(其中每个列表仅仅是一个单,然后将它们合并所有)。

我该如何递归到单例情况并同时拉出元组的两个元素?

非常感谢您提供的任何帮助。

+0

看看'where'或'let'结构。使用'where(first,second)= split ...'之类的东西。另外,你可以使用这样的结构'all @(x:xs)'将变量绑定到整个列表。 – Mark 2014-10-06 05:31:43

+2

'length'参数实现了什么? – 2014-10-06 05:46:17

+0

如果您有其他问题,请将其作为新问题发布,并且不要将其添加到现有问题中。 – Bakuriu 2014-10-06 05:53:33

回答

2

可以使用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 outght的定义来考虑空的情况下也:

+0

我希望有一天,所有的事情都对我有意义!现在,谢谢你! – Aserian 2014-10-06 05:56:30

+0

当uncurry被应用于arity大于2的函数时,它的行为是什么? – Mark 2014-10-06 06:08:43

+0

@标准答案是,在Haskell中,每个函数都只有一个(一个)。所以'a-> b-> c ===>(a,b) - > c'中的'c'也可以是'd-> e-> f - > ...'。 – 2014-10-06 06:32:35