将Show实例扩展为任何大小的元组 [英] Extend a Show instance to a Tuple of any size

查看:131
本文介绍了将Show实例扩展为任何大小的元组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用Haskell创建一个新类型的数据并创建相关的 Show 实例。我需要使用除之外的另一个分隔符创建元组Show实例。



我实现了这个代码(使用 { - #LANGUAGE FlexibleInstances# - } 编译指示):

  newtype Data = Data Double 

实例Show Data其中
show(Data dat)= show dat

实例显示(数据,数据)其中
显示(数据d1,数据d2)=显示d1 ++++显示d2

实例Show ,Data)其中
显示(数据d1,数据d2,数据d3)=显示d1 ++++显示d2 ++++显示d3

是否可以自动将Show实例扩展为任意大小的元组,而无需手动创建实例?






注意:我知道我可以使用 concat $ intersperse... 来插入列表元素之间的东西。但由于许多原因,我希望使用元组而不是列表。

/ h3>

这是因为在语言中直接支持 not ,因为Haskell中的元组是全部或全部。在Idris中,这很容易,因为(a,b,c)实际上意味着(a,(b,c))。 Haskell的懒惰会导致这种表示效率低下,无论如何,Haskell对元组的概念都有不同的概念。不过,您可以使用泛型来编写这类代码!我承诺这将是痛苦的。



为什么你要做的是一个坏主意



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

  instance(Show a,Show b)=>显示(a,b)
实例(显示a,显示b,显示c)=>显示(a,b,c)

等。当确定实例是否重叠时,您必须仅查看 => 右侧。因此,即使您的 Data 不在 Show 中,您遇到了问题。 Haskell坚持在向箭头左侧看之前选择实例。默认情况下,如果它无法唯一解析实例,则通过投诉重叠实例来实现此目的。如果你 OverlappingInstances ,你可能会使它工作,但这不是一个很好的用例。如果你使用 IncoherentInstances ,它可能会起作用,但是这是一个巨大的恶意扩展,假设它完全不存在。


I want to create a new type of data with Haskell and create the related Show instances. I need to create the tuple Show instance with another delimiter than ,.

I implemented this code (with the {-# 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

Is it possible to automatically extend the Show instance to tuples of any size without manually creating the instances?


Note : I'm aware I could use concat $ intersperse " " ... to intercalate things between list elements. But for many reasons I wish to use tuples rather than lists.

解决方案

How to write generic code for tuples

This is not supported directly in the language, because tuples in Haskell are all or nothing. In Idris, this would be easy, because (a,b,c) actually means (a,(b,c)). Haskell's laziness would make that representation inefficient, and in any case Haskell just has a different concept of what a tuple is. However, you can use generics to write that sort of code! I promise it will be painful.

Why what you're trying to do is a bad idea

The biggest problem is not that you are trying to make generic tuple code. The biggest problem is that your Show instances overlap the usual ones. The base libraries already export

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

etc. When figuring out whether instances overlap, you must look only on the right side of the =>. So even if your Data is not in Show, you have a problem. Haskell insists on committing to a choice of instance before even looking to the left of the arrow. By default, it does this by complaining about overlapping instances if it can't resolve the instance uniquely. If you OverlappingInstances, you might get it working, but this is not a good use case for that somewhat evil extension. If you use IncoherentInstances, it will probably work, but that is such a massively evil extension that it is much better to pretend it does not exist at all.

这篇关于将Show实例扩展为任何大小的元组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆