【问题标题】:Flattening tuples in Haskell在 Haskell 中扁平化元组
【发布时间】:2020-12-04 10:52:28
【问题描述】:

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

对于元组的简单情况,我可以看到我们将如何展平某些元组,如下例所示:

flatten :: (a, (b, c)) -> (a, b, c)
flatten x = (fst x, fst(snd x), snd(snd x))

flatten2 :: ((a, b), c) -> (a, b, c)
flatten2 x = (fst(fst x), snd(fst x), snd x)

但是,我正在寻找一个函数,它接受任何嵌套元组作为输入并将该元组展平。

Haskell 中可以创建这样的函数吗?

如果不能创建,为什么会这样?

【问题讨论】:

  • 是的,使用模式匹配。写一个函数(a, (b, c)) -> (a, b, c).
  • 对于任意 n 元组的情况,“generalis[ing]”到底是什么意思?如果你的意思是,'我们能不能写一个函数来接受 any 嵌套元组作为输入并将其展平',那么不,这样的函数是不可能(或至少不切实际)编写的我知道
  • @Bradm 是的,这正是我的意思。一个可以接受任何嵌套元组作为输入并将其展平的函数。
  • 旁注:如果您使用模式匹配而不是对fstsnd 的嵌套调用:flatten (a, (b, c)) = (a, b, c)
  • 您要解决的实际问题是否有更大的背景?异构列表可能是比元组更好的选择。

标签: haskell


【解决方案1】:

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

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

第二个是我们天真地对这样的功能有一些非常自然的期望,这些期望相互冲突。假设我们设法创建了一个名为flatten 的函数。如果单独来看,以下任何一段代码乍一看都非常自然:

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

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

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

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

只要付出足够的努力,就可以进行足够多的类型级编程来组合一些有时适用于有限大小元组的东西。但它是 1. 大量的前期工作,2. 很少有长期的编程效率回报,以及 3. 即使在使用站点也需要相当多的样板。这是一个糟糕的组合;如果有使用站点样板,那么您最好只编写您首先关心的功能,因为无论如何这样做通常都很短。

【讨论】:

  • 哈,我正在使用类型类和功能依赖项编写自己的答案,并且在测试时恰好遇到了重叠实例的问题!
  • @Daniel Wagner 我将在 mathstackexchange 或其他地方问一个问题,关于在某些 lambda 演算中原则上是否可行。我也很感兴趣,在 Haskell 之外,理论上是否可行。
  • @user65526 如果您的微积分有任何多态性,那么它将遇到第二个障碍。在单态演算中,只需在执行此操作的语法中添加一个术语(并将其实现为编译器魔术,例如)是没有问题的,尽管我不希望它是可以在语言中实现的东西......因为,嗯,没有多态性,对吧?我怀疑在有一种明智的方式将它自己实现为库函数之前,您需要一直到完全依赖类型,但所有运行时类型信息都会产生依赖。
  • @DanielWagner,我怀疑有一个 Haskell 等效于那个依赖的东西:要求所有组件(递归地)是 Generic(以及更多;Typeable 是更多的选择)。然后,您可以使用(类型或数据)构造函数的名称来玩游戏。
  • 哦,但是由于愚蠢的编译器性能原因,元组的 Generic 实例不会很高。 叹息
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-11
  • 1970-01-01
  • 2013-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多