在Haskell中展平元组

问题描述

在Haskell中,我们可以展平列表Flatten a list of lists

对于简单的元组,我可以看到如何平整某些元组,如以下示例所示:

startDownloadingUbiquitousItem

但是,我需要一个函数,该函数接受任何嵌套的元组作为输入并对其进行展平。

可以在Haskell中创建这样的功能吗?

如果无法创建一个,为什么会这样?

解决方法

不,这不可能。有两个障碍需要清除。

首先,所有不同大小的元组都是不同的类型构造函数。 (,)(,)彼此之间根本没有真正的联系,只不过它们碰巧是用相似的字符序列拼写的。由于Haskell中有无限多的此类构造函数,因此拥有一个对所有这些函数都做一些有趣的事情的函数将需要具有无限多个实例的typeclass。哎呀!

第二个是我们对这种功能天真地有一些期望,这些期望彼此冲突。假设我们设法创建了一个名为flatten的函数。乍看之下,以下代码块中的任何一个看上去都是很自然的:

flattenA :: ((Int,Bool),Char) -> (Int,Bool,Char)
flattenA = flatten

flattenB :: ((a,b),c) -> (a,b,c)
flattenB = flatten

flattenC :: ((Int,(Char,String)) -> (Int,Char,String)
flattenC = flatten

但是总的来说,它们似乎有点问题:如果flattenB = flattenflattenA都正确,flattenC就不可能 是正确的! flattenAflattenC的两种输入类型都与flattenB的输入类型统一-它们都是成对的,其第一个组成部分本身是一对-但flattenAflattenC返回具有不同数量组件的输出。简而言之,核心问题是当我们编写(a,b)时,我们还不知道ab本身是否是一个元组,应该“递归”展平。

通过足够的努力,可以进行足够的类型级编程,以将某些有时可用于有限大小的元组的内容组合在一起。但这是1.大量的前期工作,2.长期编程效率收益很少,以及3.即使在使用现场也需要大量样板。这是一个糟糕的组合;如果有使用现场的样板,那么您最好还是首先编写自己关心的功能,因为反正这样做通常都很短。