Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/logging/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Haskell中定义对任意递归类型的显示_Haskell_Typeclass - Fatal编程技术网

在Haskell中定义对任意递归类型的显示

在Haskell中定义对任意递归类型的显示,haskell,typeclass,Haskell,Typeclass,我正在尝试将自定义类型作为Show的实例 这是类型,它只是一个基本的集合类型 data Set a = Insert a (Set a) | EmptySet 我想要一些像 Insert 1 (Insert 2 (Insert 3 EmptySet)) 显示 {1, 2, 3} 我该怎么做?我试着用字符串连接来实现它,但似乎做字符串插值被认为是一种糟糕的形式(Haskell似乎不支持这种方式?)另外,我如何在列表中获得大括号呢?到目前为止,我所能做的只是这个,基本上什么都没做 instan

我正在尝试将自定义类型作为Show的实例

这是类型,它只是一个基本的集合类型

data Set a = Insert a (Set a) | EmptySet
我想要一些像

Insert 1 (Insert 2 (Insert 3 EmptySet))
显示

{1, 2, 3}
我该怎么做?我试着用字符串连接来实现它,但似乎做字符串插值被认为是一种糟糕的形式(Haskell似乎不支持这种方式?)另外,我如何在列表中获得大括号呢?到目前为止,我所能做的只是这个,基本上什么都没做

instance (Show a) => Show (Set a) where
     show EmptySet = ""
     show (Insert a as) = show a ++ show as 

此外,我还尝试使用Hoogle和Hayoo来查找列表实现,这样我就可以看到它是如何在列表上实现的。我找不到它。有人对此有什么建议吗?我尝试搜索“show::[a]->String”、“Data.list”、“list”等…

数据类型可能是递归的,但这不是函数递归的原因

import Data.List (intercalate)

instance Show a => Show (Set a) where
  show x = "{" ++ intercalate ", " (toList x) ++ "}"
这假设您有一个函数
toList::Set a->[a]
。递归隐藏在那里


列表的实现是通过来自的
showList
函数完成的(这样
字符串
s,也称
[Char]
s,可以以不同的方式显示)。

您的类型仍然与列表同态。无论在何处定义了
Show
实例;您仍然可以使用它:

toList (Insert a b) = a:toList b
toList EmptySet = []

instance Show a => Show (Set a) where
    show = show . toList

下面是一个直接递归的解决方案:

instance Show a => Show (Set a) where
  show = ('{' :) . go
    where
      go EmptySet            = "}"
      go (Insert x EmptySet) = show x ++ "}"
      go (Insert x xs)       = show x ++ ", " ++ go xs

如果您不喜欢
(++)
的低效使用,您当然可以使用:

应该这样做;那么,让我们测试一下:

> show (Insert 2 (Insert 3 (Insert 5 EmptySet)))
"{2, 3, 5}"

我是一个noob,但这不是因为列表必须包含所有相同类型的元素而中断吗?如果我向这个函数中输入一个数字列表,它不会发出类型错误吗?您定义的集合也必须包含相同类型的元素。在
插入a(集合a)
中,全部是
a
s。所以应该没有问题。顺便说一下,这可能是个坏主意。
show
的结果应该是有效的Haskell代码,该代码生成的值等于传递给
show
的值。我建议定义
fromList
函数,并在集合{1,2,3}上生成
show
,例如
fromList[1,2,3]
;这是标准Data.Map和Data.Set库所采用的方法。或者,您可以定义自己的函数来执行此操作,而不是调用
show
来查看此符号中的集合。如果您不喜欢
(++)
的低效使用,您应该实现
showsPrec
而不是
show
@SjoerdVisscher:我当然同意,但是我想用第一个实现来演示delta。
> show (Insert 2 (Insert 3 (Insert 5 EmptySet)))
"{2, 3, 5}"