将 Show 实例扩展为任意大小的 Tuple

Extend a Show instance to a Tuple of any size

我想用 Haskell 创建一种新的数据类型并创建相关的 Show 实例。我需要使用 , 以外的另一个定界符创建元组 Show 实例。

我实现了这段代码(使用 {-# LANGUAGE FlexibleInstances #-} pragma):

newtype Data = Data Double

instance Show Data where
  show (Data dat) = show dat

instance Show (Data,Data) where
  show (Data d1,Data d2) = show d1++" "++show d2

instance Show (Data,Data,Data) where
  show (Data d1,Data d2,Data d3) = show d1++" "++show d2++" "++show d3

是否可以在不手动创建实例的情况下自动将 Show 实例扩展到任意大小的元组?


注意:我知道我可以使用 concat $ intersperse " " ... 在列表元素之间插入内容。但出于多种原因,我希望使用元组而不是列表。

Haskell 绝对无法 编写在不同大小的元组上具有多态性的代码。

但是鉴于您似乎所做的只是创建 Data 的元组(实际上只是 Double),我不得不问...为什么不直接使用列表?您可以轻松、轻松地处理所有可能大小的列表。

如何为元组编写通用代码

语言直接支持,因为 Haskell 中的元组是全有或全无。在 Idris 中,这很容易,因为 (a,b,c) 实际上意味着 (a,(b,c))。 Haskell 的懒惰会使该表示效率低下,并且在任何情况下 Haskell 只是对什么是元组有不同的概念。但是,您可以使用 generics 来编写那种代码!我保证会很痛苦。

为什么你想做的是个坏主意

最大的问题不是您正在尝试制作通用的元组代码。最大的问题是您的 Show 实例与通常的实例重叠。基础库已经导出

instance (Show a, Show b) => Show (a, b)
instance (Show a, Show b, Show c) => Show (a,b,c)

等在确定实例是否重叠时,您必须只查看 => 右侧 。所以即使你的 Data 不在 Show 中,你也有问题。 Haskell 坚持在查看箭头左侧之前就选择实例。默认情况下,如果它不能唯一地解析实例,它会通过抱怨重叠实例来做到这一点。如果你 OverlappingInstances,你 可能 让它工作,但这不是那个有点邪恶的扩展的好用例。如果你使用 IncoherentInstances,它可能会起作用,但这是一个非常邪恶的扩展,最好假装它根本不存在。